DIRS=\\r
dapl \\r
ipoib \\r
- srp \\r
+ srp \\r
+ opensm \\r
wsd\r
--- /dev/null
+DIRS=\\r
+ user \r
--- /dev/null
+DIRS=\
+ libvendor \
+ libopensm \
+ opensm \
+ osmtest \
+ ibtrapgen
+
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
--- /dev/null
+!if $(FREEBUILD)
+TARGETNAME=ibtrapgen
+!else
+TARGETNAME=ibtrapgend
+!endif
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+ main.c \
+ ibtrapgen.c
+
+
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+ $(LIBPATH)\*\ibal.lib \
+ $(LIBPATH)\*\complib.lib \
+ $(TARGETPATH)\*\osmv_ibal.lib \
+ $(TARGETPATH)\*\opensm_ibal.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+ $(LIBPATH)\*\ibald.lib \
+ $(LIBPATH)\*\complibd.lib \
+ $(TARGETPATH)\*\osmv_ibald.lib \
+ $(TARGETPATH)\*\opensm_ibald.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+ $(OSM_HOME)\include; \
+ $(OSM_HOME); \
+ $(WINIBHOME)\inc; \
+ $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+/*
+ * Abstract:
+ * Implementation of ibtrapgen_t.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include "ibtrapgen.h"
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+#define GUID_ARRAY_SIZE 64
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ This function initializes the main object, the log and the Osm Vendor
+*/
+ib_api_status_t
+ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+ IN ibtrapgen_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ )
+{
+ ib_api_status_t status;
+
+ /* just making sure - cleanup the static global obj */
+ cl_memclr( p_ibtrapgen, sizeof( *p_ibtrapgen ) );
+
+ /* construct and init the log */
+ p_ibtrapgen->p_log = (osm_log_t *)cl_malloc(sizeof(osm_log_t));
+ osm_log_construct( p_ibtrapgen->p_log );
+ status = osm_log_init( p_ibtrapgen->p_log, p_opt->force_log_flush,
+ 0x0001, p_opt->log_file );
+ if( status != IB_SUCCESS )
+ return ( status );
+
+ osm_log_set_level( p_ibtrapgen->p_log, log_flags );
+
+ /* finaly can declare we are here ... */
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+ "ibtrapgen_init: [\n" );
+
+ /* assign all the opts */
+ p_ibtrapgen->p_opt = p_opt;
+
+ /* initialize the osm vendor service object */
+ p_ibtrapgen->p_vendor = osm_vendor_new( p_ibtrapgen->p_log,
+ p_opt->transaction_timeout );
+
+ if( p_ibtrapgen->p_vendor == NULL )
+ {
+ status = IB_INSUFFICIENT_RESOURCES;
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_init: ERR 0001: "
+ "Unable to allocate vendor object" );
+ goto Exit;
+ }
+
+ /* all mads (actually wrappers) are taken and returned to a pool */
+ osm_mad_pool_construct( &p_ibtrapgen->mad_pool );
+ status = osm_mad_pool_init(
+ &p_ibtrapgen->mad_pool, p_ibtrapgen->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+ "ibtrapgen_init: ]\n" );
+ return ( status );
+}
+
+/****f* opensm: SM/__ibtrapgen_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_rcv_callback(
+ IN osm_madw_t *p_madw,
+ IN void *bind_context,
+ IN osm_madw_t *p_req_madw )
+{
+ ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_rcv_callback );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_VERBOSE,
+ "__ibtrapgen_rcv_callback: Got callback\n",
+ cl_ntoh64(p_madw->p_mad->trans_id) );
+
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/****f* opensm: SM/__ibtrapgen_send_err_cb
+ * NAME
+ * __ibtrapgen_send_err_cb
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_send_err_cb(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_send_err_callback );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "__ibtrapgen_send_err_cb: ERR 0011: "
+ "MAD completed in error (%s).\n",
+ ib_get_err_str( p_madw->status ) );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "__ibtrapgen_send_err_cb: ERR 0012: "
+ "We shouldn't be here!! TID:0x%" PRIx64 ".\n",
+ cl_ntoh64(p_madw->p_mad->trans_id) );
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen )
+{
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+ osm_bind_info_t bind_info;
+ uint8_t i;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, ibtrapgen_bind );
+
+ /*
+ * Call the transport layer for a list of local port
+ * GUID values.
+ */
+ status = osm_vendor_get_all_port_attr( p_ibtrapgen->p_vendor,
+ attr_array, &num_ports );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0002: "
+ "Failure getting local port attributes (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /* make sure the requested port exists */
+ if ( p_ibtrapgen->p_opt->port_num > num_ports )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0003: "
+ "Given port number out of range %u > %u\n",
+ p_ibtrapgen->p_opt->port_num , num_ports );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+
+ for ( i = 0 ; i < num_ports ; i++ )
+ {
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+ "ibtrapgen_bind: Found port number:%u "
+ " with GUID:0x%016"PRIx64"\n",
+ i, cl_ntoh64(attr_array[i].port_guid) );
+ }
+ /* check if the port is active */
+/* if (attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state < 4) */
+/* { */
+/* osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, */
+/* "ibtrapgen_bind: ERR 0004: " */
+/* "Given port number link state is not active: %s.\n", */
+/* ib_get_port_state_str( */
+/* attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state ) */
+/* ); */
+/* status = IB_NOT_FOUND; */
+/* goto Exit; */
+/* } */
+
+ p_ibtrapgen->port_guid = attr_array[p_ibtrapgen->p_opt->port_num - 1].port_guid;
+ /* save sm_lid as we need it when sending the Trap (dest lid)*/
+ p_ibtrapgen->p_opt->sm_lid = attr_array[p_ibtrapgen->p_opt->port_num - 1].sm_lid;
+
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+ "ibtrapgen_bind: Port Num:%u "
+ "GUID:0x%016"PRIx64"\n",
+ p_ibtrapgen->p_opt->port_num,
+ p_ibtrapgen->port_guid );
+
+ /* ok finaly bind the sa interface to this port */
+ /* TODO - BIND LIKE THE osm_sm_mad_ctrl does */
+ bind_info.class_version = 1;
+ bind_info.is_report_processor = TRUE;
+ bind_info.is_responder = TRUE;
+ bind_info.is_trap_processor = TRUE;
+ bind_info.mad_class = IB_MCLASS_SUBN_DIR;
+ bind_info.port_guid = p_ibtrapgen->port_guid;
+ bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+ bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+ "ibtrapgen_bind: Trying to bind to GUID:0x%016"PRIx64"\n",
+ bind_info.port_guid );
+
+ p_ibtrapgen->h_bind = osm_vendor_bind( p_ibtrapgen->p_vendor,
+ &bind_info,
+ &p_ibtrapgen->mad_pool,
+ __ibtrapgen_rcv_callback,
+ __ibtrapgen_send_err_cb,
+ p_ibtrapgen );
+
+ if( p_ibtrapgen->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0005: "
+ "Unable to bind to SA\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen )
+{
+ if( p_ibtrapgen->p_vendor )
+ {
+ osm_vendor_delete( &p_ibtrapgen->p_vendor );
+ }
+
+ osm_log_destroy( p_ibtrapgen->p_log );
+ cl_free( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen )
+{
+ osm_madw_t* p_report_madw;
+ ib_mad_notice_attr_t* p_report_ntc;
+ ib_mad_t* p_mad;
+ ib_smp_t* p_smp_mad;
+ osm_mad_addr_t mad_addr;
+ static atomic32_t trap_fwd_trans_id = 0x02DAB000;
+ ib_api_status_t status;
+ osm_log_t *p_log = p_ibtrapgen->p_log;
+ uint16_t i;
+
+ OSM_LOG_ENTER( p_log, ibtrapgen_run );
+
+ osm_log( p_log, OSM_LOG_INFO,
+ "ibtrapgen_run: "
+ "Sending trap:%u from LID:0x%X %u times\n",
+ p_ibtrapgen->p_opt->trap_num,
+ p_ibtrapgen->p_opt->lid,
+ p_ibtrapgen->p_opt->number );
+
+ printf("-V- SM lid is : 0x%04X\n",p_ibtrapgen->p_opt->sm_lid);
+ mad_addr.dest_lid = cl_ntoh16(p_ibtrapgen->p_opt->sm_lid);
+ /* ??? - what is path_bits? What should be the value here?? */
+ mad_addr.path_bits = 0;
+ /* ??? - what is static_rate? What should be the value here?? */
+ mad_addr.static_rate = 0;
+
+ mad_addr.addr_type.smi.source_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ mad_addr.addr_type.smi.port_num = p_ibtrapgen->p_opt->src_port;
+
+ for (i = 1 ; i <= p_ibtrapgen->p_opt->number ; i++ )
+ {
+ p_report_madw = osm_mad_pool_get( &p_ibtrapgen->mad_pool,
+ p_ibtrapgen->h_bind,
+ MAD_BLOCK_SIZE,
+ &mad_addr );
+
+ if( !p_report_madw )
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "ibtrapgen_run: ERR 00020: "
+ "osm_mad_pool_get failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_report_madw->resp_expected = FALSE;
+
+ /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+ p_mad = osm_madw_get_mad_ptr( p_report_madw );
+ ib_mad_init_new(p_mad,
+ IB_MCLASS_SUBN_LID,
+ 1,
+ IB_MAD_METHOD_TRAP,
+ cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+ IB_MAD_ATTR_NOTICE,
+ 0);
+
+ p_smp_mad = osm_madw_get_smp_ptr( p_report_madw );
+
+ /* The payload is analyzed as mad notice attribute */
+ p_report_ntc = (ib_mad_notice_attr_t*)(ib_smp_get_payload_ptr(p_smp_mad));
+
+ cl_memclr( p_report_ntc, sizeof(*p_report_ntc) );
+ p_report_ntc->generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type(p_report_ntc, 2); /* A switch generator */
+ p_report_ntc->g_or_v.generic.trap_num = cl_hton16(p_ibtrapgen->p_opt->trap_num);
+ p_report_ntc->issuer_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ if (p_ibtrapgen->p_opt->trap_num == 128)
+ {
+ p_report_ntc->data_details.ntc_128.sw_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ }
+ else
+ {
+ p_report_ntc->data_details.ntc_129_131.lid =
+ cl_hton16(p_ibtrapgen->p_opt->lid);
+ p_report_ntc->data_details.ntc_129_131.port_num =
+ p_ibtrapgen->p_opt->src_port;
+ }
+
+ status = osm_vendor_send(p_report_madw->h_bind, p_report_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "ibtrapgen_run: ERR 0021: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+ osm_log(p_log, OSM_LOG_INFO,
+ "ibtrapgen_run: "
+ "Sent trap number:%u out of:%u\n",
+ i,
+ p_ibtrapgen->p_opt->number );
+ /* sleep according to rate time. The usleep is in usec - need to revert
+ the milisecs to usecs. */
+ usleep(p_ibtrapgen->p_opt->rate*1000);
+ }
+
+ Exit:
+ // sleep(3);
+ OSM_LOG_EXIT( p_log );
+ return(status);
+}
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ * Declaration of ibtrapgen_t.
+ * This object represents the ibtrapgen object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#ifndef _IBTRAPGEN_H_
+#define _IBTRAPGEN_H_
+
+#include <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+/****h* Trap_Generator_App/Ibtrapgen
+ * NAME
+ * Ibtrapgen
+ *
+ * DESCRIPTION
+ * The Ibtrapgen object create/join and leave multicast group.
+ *
+ * AUTHOR
+ * Yael Kalka, Mellanox.
+ *
+ *********/
+
+/****s* Trap_Generator_App/ibtrapgen_opt_t
+ * NAME
+ * ibtrapgen_opt_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen options structure. This structure contains the various
+ * specific configuration parameters for ibtrapgen.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen_opt
+{
+ uint8_t trap_num;
+ uint16_t number;
+ uint16_t rate;
+ uint16_t lid;
+ uint16_t sm_lid;
+ uint8_t src_port;
+ uint8_t port_num;
+ uint32_t transaction_timeout;
+ boolean_t force_log_flush;
+ char *log_file;
+} ibtrapgen_opt_t;
+/*
+ * FIELDS
+ *
+ * trap_num
+ * Trap number to generate.
+ *
+ * number
+ * Number of times trap should be generated.
+ *
+ * rate
+ * Rate of trap generation (in miliseconds)
+ *
+ * lid
+ * Lid from which the trap should be generated.
+ *
+ * src_port
+ * Source port from which the trap should be generated.
+ *
+ * port_num
+ * Port num used for communicating with the SA.
+ *
+ * SEE ALSO
+ *********/
+
+/****s* Trap Generator App/ibtrapgen_t
+ * NAME
+ * ibtrapgen_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen structure.
+ *
+ * This object should be treated as opaque and should
+ * be manipulated only through the provided functions.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen
+{
+ osm_log_t *p_log;
+ struct _osm_vendor *p_vendor;
+ osm_bind_handle_t h_bind;
+ osm_mad_pool_t mad_pool;
+
+ ibtrapgen_opt_t *p_opt;
+ ib_net64_t port_guid;
+} ibtrapgen_t;
+/*
+ * FIELDS
+ * p_log
+ * Log facility used by all Ibtrapgen components.
+ *
+ * p_vendor
+ * Pointer to the vendor transport layer.
+ *
+ * h_bind
+ * The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa
+ *
+ * mad_pool
+ * The mad pool provided for teh vendor layer to allocate mad wrappers in
+ *
+ * p_opt
+ * ibtrapgen options structure
+ *
+ * guid
+ * guid for the port over which ibtrapgen is running.
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_destroy
+ * NAME
+ * ibtrapgen_destroy
+ *
+ * DESCRIPTION
+ * The ibtrapgen_destroy function destroys an ibtrapgen object, releasing
+ * all resources.
+ *
+ * SYNOPSIS
+ */
+void ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to a Trap_Generator_App object to destroy.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Performs any necessary cleanup of the specified Trap_Generator_App object.
+ * Further operations should not be attempted on the destroyed object.
+ * This function should only be called after a call to ibtrapgen_init.
+ *
+ * SEE ALSO
+ * ibtrapgen_init
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_init
+ * NAME
+ * ibtrapgen_init
+ *
+ * DESCRIPTION
+ * The ibtrapgen_init function initializes a Trap_Generator_App object for use.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+ IN ibtrapgen_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_t object to initialize.
+ *
+ * p_opt
+ * [in] Pointer to the options structure.
+ *
+ * log_flags
+ * [in] Log level flags to set.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if the Trap_Generator_App object was initialized successfully.
+ *
+ * NOTES
+ * Allows calling other Trap_Generator_App methods.
+ *
+ * SEE ALSO
+ * ibtrapgen object, ibtrapgen_construct, ibtrapgen_destroy
+ *********/
+
+
+/****f* Trap_Generator_App/ibtrapgen_bind
+ * NAME
+ * ibtrapgen_bind
+ *
+ * DESCRIPTION
+ * Binds ibtrapgen to a local port.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen );
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if OK
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_run
+ * NAME
+ * ibtrapgen_run
+ *
+ * DESCRIPTION
+ * Runs the ibtrapgen flow: Creation of traps.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS on success
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+#endif /* */
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ * Command line interface for ibtrapgen.
+ * Parse and fill in the options and call the actual code.
+ * Implemented in ibtrapgen:
+ * Initialize the ibmgrp object (and log)
+ * Bind ibmgrp to the requested IB port.
+ * Run the actual command
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN__
+#include <getopt.h>
+#endif
+#include <complib/cl_debug.h>
+#include <errno.h>
+#include "ibtrapgen.h"
+
+#define DEFAULT_RETRY_COUNT 3
+#define DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+ibtrapgen_is_debug()
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage( )
+{
+ printf( "\n------- ibtrapgen - Usage and options ----------------------\n" );
+ printf( "Usage: one of the following optional flows:\n" );
+ printf(" ibtrapgen -t|--trap_num <TRAP_NUM> -n|--number <NUM_TRAP_CREATIONS>\n"
+ " -r|--rate <TRAP_RATE> -l|--lid <LIDADDR> \n"
+ " -s|--src_port <SOURCE_PORT> -p|--port_num <PORT_NUM>\n" );
+ printf( "\nOptions:\n" );
+ printf( "-t <TRAP_NUM>\n"
+ "--trap_num <TRAP_NUM>\n"
+ " This option specifies the number of the trap to generate.\n"
+ " Valid values are 128-131.\n" );
+ printf( "-n <NUM_TRAP_CREATIONS>\n"
+ "--number <NUM_TRAP_CREATIONS>\n"
+ " This option specifies the number of times to generate this trap.\n"
+ " If not specified - default to 1.\n" );
+ printf( "-r <TRAP_RATE>\n"
+ "--rate <TRAP_RATE>\n"
+ " This option specifies the rate of the trap generation.\n"
+ " What is the time period between one generation and another?\n"
+ " The value is given in miliseconds. \n"
+ " If the number of trap creations is 1 - this value is ignored.\n" );
+ printf( "-l <LIDADDR>\n"
+ "--lid <LIDADDR>\n"
+ " This option specifies the lid address from where the trap should\n"
+ " be generated.\n" );
+ printf( "-s <SOURCE_PORT>\n"
+ "--src_port <SOURCE_PORT>\n"
+ " This option specifies the port number from which the trap should\n"
+ " be generated. If trap number is 128 - this value is ignored (since\n"
+ " trap 128 is not sent with a specific port number)\n" );
+ printf( "-p <port num>\n"
+ "--port_num <port num>\n"
+ " This is the port number used for communicating with\n"
+ " the SA.\n" );
+ printf( "-h\n"
+ "--help\n" " Display this usage info then exit.\n\n" );
+ printf( "-o\n"
+ "--out_log_file\n"
+ " This option defines the log to be the given file.\n"
+ " By default the log goes to stdout.\n\n");
+ printf( "-v\n"
+ " This option increases the log verbosity level.\n"
+ " The -v option may be specified multiple times\n"
+ " to further increase the verbosity level.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-V\n"
+ " This option sets the maximum verbosity level and\n"
+ " forces log flushing.\n"
+ " The -V is equivalent to '-vf 0xFF -d 2'.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-x <flags>\n"
+ " This option sets the log verbosity level.\n"
+ " A flags field must follow the -vf option.\n"
+ " A bit set/clear in the flags enables/disables a\n"
+ " specific log level as follows:\n"
+ " BIT LOG LEVEL ENABLED\n"
+ " ---- -----------------\n"
+ " 0x01 - ERROR (error messages)\n"
+ " 0x02 - INFO (basic messages, low volume)\n"
+ " 0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+ " 0x08 - DEBUG (diagnostic, high volume)\n"
+ " 0x10 - FUNCS (function entry/exit, very high volume)\n"
+ " 0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+ " 0x40 - currently unused.\n"
+ " 0x80 - currently unused.\n"
+ " Without -x, ibtrapgen defaults to ERROR + INFO (0x3).\n"
+ " Specifying -x 0 disables all messages.\n"
+ " Specifying -x 0xFF enables all messages (see -V).\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ Converts a GID string of the format 0xPPPPPPPPPPPPPPPP:GGGGGGGGGGGGGGGG
+ to a gid type
+*/
+int
+str2gid(
+ IN char *str,
+ OUT ib_gid_t *p_gid
+ );
+
+int
+str2gid(
+ IN char *str,
+ OUT ib_gid_t *p_gid
+ )
+{
+ ib_gid_t temp;
+ char buf[38];
+ char *p_prefix, *p_guid;
+
+ CL_ASSERT(p_gid);
+
+ strcpy(buf, str);
+ p_prefix = buf;
+ /*p_guid = index(buf, ':');*/
+ p_guid = strchr( buf, ':' );
+
+ if (! p_guid)
+ {
+ printf("Wrong format for gid %s\n", buf);
+ return 1;
+ }
+
+ *p_guid = '\0';
+ p_guid++;
+
+ errno = 0;
+ temp.unicast.prefix = cl_hton64(strtoull(p_prefix, NULL, 0));
+ if (errno) {
+ printf("Wrong format for gid prefix:%s (got %u)\n",
+ p_prefix, errno);
+ return 1;
+ }
+
+ temp.unicast.interface_id = cl_hton64(strtoull(p_guid, NULL, 16));
+ if (errno) {
+ printf("Wrong format for gid guid:%s\n", p_guid);
+ return 1;
+ }
+
+ *p_gid = temp;
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+ char *argv[] )
+{
+ static ibtrapgen_t ibtrapgen;
+ ibtrapgen_opt_t opt = { 0 };
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+ uint32_t next_option;
+ const char *const short_option = "t:n:r:s:l:p:o:vVh";
+
+ /*
+ * In the array below, the 2nd parameter specified the number
+ * of arguments as follows:
+ * 0: no arguments
+ * 1: argument
+ * 2: optional
+ */
+ const struct option long_option[] = {
+ {"trap_num", 1, NULL, 't'},
+ {"number", 1, NULL, 'n'},
+ {"rate", 1, NULL, 'r'},
+ {"lid", 1, NULL, 'l'},
+ {"src_port", 1, NULL, 's'},
+ {"port_num", 1, NULL, 'p'},
+ {"help", 0, NULL, 'h'},
+ {"verbose", 0, NULL, 'v'},
+ {"out_log_file", 1, NULL, 'o'},
+ {"vf", 1, NULL, 'x'},
+ {"V", 0, NULL, 'V'},
+
+ {NULL, 0, NULL, 0} /* Required at end of array */
+ };
+
+
+ opt.trap_num = 0;
+ opt.number = 1; /* This is the default value */
+ opt.rate = 0;
+ opt.lid = 0;
+ opt.src_port = 0;
+ opt.port_num = 0;
+ opt.log_file = NULL;
+ opt.force_log_flush = FALSE;
+ opt.transaction_timeout = DEFAULT_TRANS_TIMEOUT_MILLISEC;
+
+ do
+ {
+ next_option = getopt_long_only( argc, argv, short_option,
+ long_option, NULL );
+
+ switch ( next_option )
+ {
+ case 't':
+ /*
+ * Define the trap number
+ */
+ opt.trap_num = (uint8_t)atoi( optarg );
+ if ((opt.trap_num < 128) || (opt.trap_num > 131))
+ {
+ printf( "-E- Given trap number is illegal! \n"
+ " Supportes generation of traps 128-131.\n" );
+ exit(1);
+ }
+ printf( "-I- Trap Number = %u\n", opt.trap_num );
+ break;
+
+ case 'n':
+ /*
+ * Define the number of occurences
+ */
+ opt.number = (uint16_t)atoi( optarg );
+
+ printf( "-I- Number Trap Occurences = %u\n", opt.number );
+ break;
+
+ case 'r':
+ /*
+ * Define the rate of the trap
+ */
+ opt.rate = (uint16_t)atoi( optarg );
+
+ printf( "-I- Trap Rate = %u miliseconds\n", opt.rate );
+ break;
+
+
+ case 'l':
+ /*
+ * Define the source lid of the trap
+ */
+ opt.lid = (uint16_t)strtoul( optarg , NULL , 16);
+
+ printf( "-I- Trap Lid = 0x%04X\n", opt.lid );
+ break;
+
+ case 's':
+ /*
+ * Define the source port number of the trap
+ */
+ opt.src_port = (uint8_t)atoi( optarg );
+
+ printf( "-I- Trap Port Number = %u\n", opt.src_port );
+ break;
+
+ case 'p':
+ /*
+ * Specifies port guid with which to bind.
+ */
+ opt.port_num = (uint8_t)atoi( optarg );
+ printf( "-I- Port Num:%u\n", opt.port_num );
+ break;
+
+ case 'o':
+ opt.log_file = optarg;
+ printf("-I- Log File:%s\n", opt.log_file );
+ break;
+
+ case 'v':
+ /*
+ * Increases log verbosity.
+ */
+ log_flags = ( log_flags << 1 ) | 1;
+ printf( "-I- Verbose option -v (log flags = 0x%X)\n", log_flags );
+ break;
+
+ case 'V':
+ /*
+ * Specifies maximum log verbosity.
+ */
+ log_flags = 0xFFFFFFFF;
+ opt.force_log_flush = TRUE;
+ printf( "-I- Enabling maximum log verbosity\n" );
+ break;
+
+ case 'h':
+ show_usage( );
+ return 0;
+
+ case 'x':
+ log_flags = strtol( optarg, NULL, 0 );
+ printf( "-I- Verbose option -vf (log flags = 0x%X)\n",
+ log_flags );
+ break;
+
+ case -1:
+ /* printf( "Done with args\n" ); */
+ break;
+
+ default: /* something wrong */
+ abort( );
+ }
+
+ }
+ while( next_option != -1 );
+
+ /* Check for mandatory options */
+ if (opt.trap_num == 0)
+ {
+ printf( "-E- Missing trap number.\n" );
+ exit(1);
+ }
+ if (opt.lid == 0)
+ {
+ printf( "-E- Missing lid.\n" );
+ exit(1);
+ }
+ if (opt.src_port == 0 && opt.trap_num >= 129 && opt.trap_num <= 131)
+ {
+ /* for trap 129-131 should be given source port number */
+ printf( "-E- source port number.\n" );
+ exit(1);
+ }
+ if (opt.port_num == 0)
+ {
+ printf( "-E- Missing port number.\n" );
+ exit(1);
+ }
+ if (opt.rate == 0 && opt.number > 1)
+ {
+ /* for number of traps greater than 1 need to give the rate for the
+ trap generation. */
+ printf( "-E- Missing rate.\n" );
+ exit(1);
+ }
+
+
+ /* init the main object and sub objects (log and osm vendor) */
+ status = ibtrapgen_init( &ibtrapgen, &opt, ( osm_log_level_t ) log_flags );
+ if( status != IB_SUCCESS )
+ {
+ printf("-E- fail to init ibtrapgen.\n");
+ goto Exit;
+ }
+
+ /* bind to a specific port */
+ status = ibtrapgen_bind( &ibtrapgen );
+ if (status != IB_SUCCESS) exit(status);
+
+ /* actual work */
+ status = ibtrapgen_run( &ibtrapgen );
+ if (status != IB_SUCCESS)
+ {
+ printf("IBTRAPGEN: FAIL\n");
+ }
+ else
+ {
+ printf("IBTRAPGEN: PASS\n");
+ }
+
+ //ibtrapgen_destroy( &ibtrapgen );
+
+ Exit:
+ exit ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * provides byteswapping utilities. Basic fuctions are obtained from platform
+ * specific implementations from ibyteswap_osd.h.
+ *
+ * Environment:
+ * All
+ */
+
+
+#ifndef _CL_BYTESWAP_H_
+#define _CL_BYTESWAP_H_
+
+
+#include <complib/cl_memory.h>
+#include <complib/cl_byteswap_osd.h>
+
+
+/****h* Component Library/Byte Swapping
+* NAME
+* Byte Swapping
+*
+* DESCRIPTION
+* The byte swapping functions and macros allow swapping bytes from network
+* byte order to host byte order.
+*
+* All data transmitted between systems should be in network byte order.
+* In order to utilize such data, it must be converted to host byte order
+* before use.
+*
+* SEE ALSO
+* Functions:
+* cl_ntoh16, cl_hton16, cl_ntoh32, cl_hton32, cl_ntoh64, cl_hton64,
+* cl_ntoh
+*
+* Macros:
+* CL_NTOH16, CL_HTON16, CL_NTOH32, CL_HTON32, CL_NTOH64, CL_HTON64
+*********/
+
+
+/*
+ * The ibyteswap_osd.h provides the following macros.
+ * __LITTLE_ENDIAN
+ * __BIG_ENDIAN
+ * __BYTE_ORDER
+ *
+ * If the platform provides byte swapping functions, ibyteswap_osd.h also
+ * provides the following macros.
+ * ntoh16, hton16
+ * ntoh32, hton32
+ * ntoh64, hton64
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH16
+* NAME
+* CL_NTOH16
+*
+* DESCRIPTION
+* The CL_NTOH16 macro converts a 16-bit value from network byte order to
+* host byte order. The CL_NTOH16 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_NTOH16 is less efficient
+* than the cl_ntoh16 function.
+*
+* SYNOPSIS
+* CL_NTOH16( val );
+*
+* PARAMETERS
+* val
+* [in] 16-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+* Value of val converted to host byte order.
+*
+* NOTES
+* This macro is analogous to CL_HTON16.
+*
+* SEE ALSO
+* Byte Swapping, CL_HTON16, CL_NTOH32, CL_NTOH64,
+* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON16
+* NAME
+* CL_HTON16
+*
+* DESCRIPTION
+* The CL_HTON16 macro converts a 16-bit value from host byte order to
+* network byte order. The CL_HTON16 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_HTON16 is less efficient
+* than the cl_hton16 function.
+*
+* SYNOPSIS
+* CL_HTON16( val );
+*
+* PARAMETERS
+* val
+* [in] 16-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+* Value of val converted to network byte order.
+*
+* NOTES
+* This macro is analogous to CL_NTOH16.
+*
+* SEE ALSO
+* Byte Swapping, CL_NTOH16, CL_HTON32, CL_HTON64,
+* cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+ #define CL_NTOH16( x ) (uint16_t)( \
+ (((uint16_t)(x) & 0x00FF) << 8) | \
+ (((uint16_t)(x) & 0xFF00) >> 8) )
+#else
+ #define CL_NTOH16( x ) (x)
+#endif
+#define CL_HTON16 CL_NTOH16
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh16
+* NAME
+* cl_ntoh16
+*
+* DESCRIPTION
+* The cl_ntoh16 function converts a 16-bit value from network byte order to
+* host byte order.
+*
+* SYNOPSIS
+* uint16_t
+* cl_ntoh16(
+* IN const uint16_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+* Value of val converted to host byte order.
+*
+* NOTES
+* This function is analogous to cl_hton16.
+*
+* SEE ALSO
+* Byte Swapping, cl_hton16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton16
+* NAME
+* cl_hton16
+*
+* DESCRIPTION
+* The cl_hton16 function converts a 16-bit value from host byte order to
+* network byte order.
+*
+* SYNOPSIS
+* uint16_t
+* cl_hton16(
+* IN const uint16_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+* Value of val converted to network byte order.
+*
+* NOTES
+* This function is analogous to cl_ntoh16.
+*
+* SEE ALSO
+* Byte Swapping, cl_ntoh16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#undef cl_ntoh16
+#undef cl_hton16
+#ifndef cl_ntoh16
+ #define cl_ntoh16 CL_NTOH16
+ #define cl_hton16 CL_HTON16
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH32
+* NAME
+* CL_NTOH32
+*
+* DESCRIPTION
+* The CL_NTOH32 macro converts a 32-bit value from network byte order to
+* host byte order. The CL_NTOH32 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_NTOH32 is less efficient
+* than the cl_ntoh32 function.
+*
+* SYNOPSIS
+* CL_NTOH32( val );
+*
+* PARAMETERS
+* val
+* [in] 32-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+* Value of val converted to host byte order.
+*
+* NOTES
+* This macro is analogous to CL_HTON32.
+*
+* SEE ALSO
+* Byte Swapping, CL_HTON32, CL_NTOH16, CL_NTOH64,
+* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON32
+* NAME
+* CL_HTON32
+*
+* DESCRIPTION
+* The CL_HTON32 macro converts a 32-bit value from host byte order to
+* network byte order. The CL_HTON32 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_HTON32 is less efficient
+* than the cl_hton32 function.
+*
+* SYNOPSIS
+* CL_HTON32( val );
+*
+* PARAMETERS
+* val
+* [in] 32-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+* Value of val converted to network byte order.
+*
+* NOTES
+* This macro is analogous to CL_NTOH32.
+*
+* SEE ALSO
+* Byte Swapping, CL_NTOH32, CL_HTON16, CL_HTON64,
+* cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+ #define CL_NTOH32( x ) (uint32_t)( \
+ (((uint32_t)(x) & 0x000000FF) << 24) | \
+ (((uint32_t)(x) & 0x0000FF00) << 8) | \
+ (((uint32_t)(x) & 0x00FF0000) >> 8) | \
+ (((uint32_t)(x) & 0xFF000000) >> 24) )
+#else
+ #define CL_NTOH32( x ) (x)
+#endif
+#define CL_HTON32 CL_NTOH32
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh32
+* NAME
+* cl_ntoh32
+*
+* DESCRIPTION
+* The cl_ntoh32 function converts a 32-bit value from network byte order to
+* host byte order.
+*
+* SYNOPSIS
+* uint32_t
+* cl_ntoh32(
+* IN const uint32_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+* Value of val converted in host byte order.
+*
+* NOTES
+* This function is analogous to cl_hton32.
+*
+* SEE ALSO
+* Byte Swapping, cl_hton32, cl_ntoh16, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton32
+* NAME
+* cl_hton32
+*
+* DESCRIPTION
+* The cl_hton32 function converts a 32-bit value from host byte order to
+* network byte order.
+*
+* SYNOPSIS
+* uint32_t
+* cl_hton32(
+* IN const uint32_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+* Value of val converted to network byte order.
+*
+* NOTES
+* This function is analogous to cl_ntoh32.
+*
+* SEE ALSO
+* Byte Swapping, cl_ntoh32, cl_hton16, cl_hton64, cl_ntoh
+*********/
+#undef cl_ntoh32
+#undef cl_hton32
+#ifndef cl_ntoh32
+ #define cl_ntoh32 CL_NTOH32
+ #define cl_hton32 CL_HTON32
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH64
+* NAME
+* CL_NTOH64
+*
+* DESCRIPTION
+* The CL_NTOH64 macro converts a 64-bit value from network byte order to
+* host byte order. The CL_NTOH64 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_NTOH64 is less efficient
+* than the cl_ntoh64 function.
+*
+* SYNOPSIS
+* CL_NTOH64( val );
+*
+* PARAMETERS
+* val
+* [in] 64-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+* Value of val converted to host byte order.
+*
+* NOTES
+* This macro is analogous to CL_HTON64.
+*
+* SEE ALSO
+* Byte Swapping, CL_HTON64, CL_NTOH16, CL_NTOH32,
+* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON64
+* NAME
+* CL_HTON64
+*
+* DESCRIPTION
+* The CL_HTON64 macro converts a 64-bit value from host byte order to
+* network byte order. The CL_HTON64 macro will cause constant values to be
+* swapped by the pre-processor. For variables, CL_HTON64 is less efficient
+* than the cl_hton64 function.
+*
+* SYNOPSIS
+* CL_HTON64( val );
+*
+* PARAMETERS
+* val
+* [in] 64-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+* Value of val converted to network byte order.
+*
+* NOTES
+* This macro is analogous to CL_NTOH64.
+*
+* SEE ALSO
+* Byte Swapping, CL_NTOH64, CL_HTON16, CL_HTON32,
+* cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+ #define CL_NTOH64( x ) (uint64_t)( \
+ (((uint64_t)(x) & CL_CONST64(0x00000000000000FF)) << 56) | \
+ (((uint64_t)(x) & CL_CONST64(0x000000000000FF00)) << 40) | \
+ (((uint64_t)(x) & CL_CONST64(0x0000000000FF0000)) << 24) | \
+ (((uint64_t)(x) & CL_CONST64(0x00000000FF000000)) << 8 ) | \
+ (((uint64_t)(x) & CL_CONST64(0x000000FF00000000)) >> 8 ) | \
+ (((uint64_t)(x) & CL_CONST64(0x0000FF0000000000)) >> 24) | \
+ (((uint64_t)(x) & CL_CONST64(0x00FF000000000000)) >> 40) | \
+ (((uint64_t)(x) & CL_CONST64(0xFF00000000000000)) >> 56) )
+#else
+ #define CL_NTOH64( x ) (x)
+#endif
+#define CL_HTON64 CL_NTOH64
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh64
+* NAME
+* cl_ntoh64
+*
+* DESCRIPTION
+* The cl_ntoh64 function converts a 64-bit value from network byte order to
+* host byte order.
+*
+* SYNOPSIS
+* uint64_t
+* cl_ntoh64(
+* IN const uint64_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+* Value of val converted in host byte order.
+*
+* NOTES
+* This function is analogous to cl_hton64.
+*
+* SEE ALSO
+* Byte Swapping, cl_hton64, cl_ntoh16, cl_ntoh32, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton64
+* NAME
+* cl_hton64
+*
+* DESCRIPTION
+* The cl_hton64 function converts a 64-bit value from host byte order to
+* network byte order.
+*
+* SYNOPSIS
+* uint64_t
+* cl_hton64(
+* IN const uint64_t val );
+*
+* PARAMETERS
+* val
+* [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+* Value of val converted to network byte order.
+*
+* NOTES
+* This function is analogous to cl_ntoh64.
+*
+* SEE ALSO
+* Byte Swapping, cl_ntoh64, cl_hton16, cl_hton32, cl_ntoh
+*********/
+#undef cl_ntoh64
+#undef cl_hton64
+#ifndef cl_ntoh64
+ #define cl_ntoh64 CL_NTOH64
+ #define cl_hton64 CL_HTON64
+#endif
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh
+* NAME
+* cl_ntoh
+*
+* DESCRIPTION
+* The cl_ntoh function converts a value from network byte order to
+* host byte order.
+*
+* SYNOPSIS
+*/
+CL_INLINE void CL_API
+cl_ntoh(
+ OUT char* const p_dest,
+ IN const char* const p_src,
+ IN const uint8_t size )
+{
+#if CPU_LE
+ uint8_t i;
+ char temp;
+
+ if( p_src == p_dest )
+ {
+ /* Swap in place if source and destination are the same. */
+ for( i = 0; i < size / 2; i++ )
+ {
+ temp = p_dest[i];
+ p_dest[i] = p_src[size - 1 - i];
+ p_dest[size - 1 - i] = temp;
+ }
+ }
+ else
+ {
+ for( i = 0; i < size; i++ )
+ p_dest[i] = p_src[size - 1 - i];
+ }
+#else
+ /*
+ * If the source and destination are not the same, copy the source to
+ * the destination.
+ */
+ if( p_src != p_dest )
+ cl_memcpy( p_dest, p_src, size );
+#endif
+}
+/*
+* PARAMETERS
+* p_dest
+* [in] Pointer to a byte array to contain the converted value of p_src.
+*
+* p_src
+* [in] Pointer to a byte array to be converted from network byte
+* ordering.
+*
+* size
+* [in] Number of bytes to swap.p_dest
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* cl_ntoh can perform in place swapping if both p_src and p_dest point to
+* the same buffer.
+*
+* SEE ALSO
+* Byte Swapping, cl_ntoh16, cl_ntoh32, cl_ntoh64
+*********/
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CL_BYTESWAP_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id: cl_signal_osd.h 47 2005-05-30 18:00:40Z sleybo $
+ */
+
+/*
+ * Abstract:
+ * Declaration of Signal Handler Registration
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _CL_SIG_HDL_H_
+#define _CL_SIG_HDL_H_
+
+#include <signal.h>
+
+/****h* Component Library/Signal Handler
+* NAME
+* Signal Handler Registration
+*
+* DESCRIPTION
+* The Signal Handler Registration allows to register a callback on the case of incoming signal
+*
+* SEE ALSO
+*********/
+/* TODO : Required when calling signal function in windows*/
+typedef void (__cdecl *cl_sig_hdl)(
+ IN int sig);
+/* Prototypes */
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+* cl_reg_sig_hdl
+*
+* DESCRIPTION
+* Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+
+static inline void
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl);
+
+
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+* cl_sig_mask_sigint
+*
+* DESCRIPTION
+* Mask the kill signal
+*
+* SYNOPSIS
+*/
+
+static inline void
+cl_sig_mask_sigint(void);
+
+
+
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+* cl_reg_sig_hdl
+*
+* DESCRIPTION
+* Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+static inline void
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl) {
+ signal(sig,pfn_sig_hdl);
+ }
+/*
+*********/
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+* cl_sig_mask_sigint
+*
+* DESCRIPTION
+* Mask the kill signal
+*
+* SYNOPSIS
+*/
+static inline void
+cl_sig_mask_sigint(void)
+{
+
+}
+/*
+*********/
+
+#endif /* _CL_SIG_HDL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 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.
+ *
+ * $Id: osm_sa.c 3155 2005-08-22 12:09:34Z yael $
+ */
+
+
+#if !defined(__IB_TYPES_H__)
+#define __IB_TYPES_H__
+
+#include <complib/cl_types.h>
+#include <complib/cl_byteswap.h>
+#include <complib/cl_memory.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#if defined( WIN32 ) || defined( _WIN64 )
+ #if defined( EXPORT_AL_SYMBOLS )
+ #define AL_EXPORT __declspec(dllexport)
+ #else
+ #define AL_EXPORT __declspec(dllimport)
+ #endif
+
+ #ifdef CL_KERNEL
+ #define AL_API
+ #define AL_INLINE static inline
+ #else
+ #define AL_API __stdcall
+ #define AL_INLINE AL_EXPORT inline
+ /* Defined for some unique access function that are defined only in osm ib_types */
+ #define OSM_INLINE static inline
+ #endif /* CL_KERNEL */
+#else
+ #define AL_EXPORT extern
+ #define AL_INLINE static inline
+ #define OSM_INLINE static inline
+ #define AL_API
+ #define __ptr64
+#endif
+
+
+
+/****h* IBA Base/Constants
+* NAME
+* Constants
+*
+* DESCRIPTION
+* The following constants are used throughout the IBA code base.
+*
+* Definitions are from the InfiniBand Architecture Specification v1.1
+*
+*********/
+
+/****d* IBA Base: Constants/MAD_BLOCK_SIZE
+* NAME
+* MAD_BLOCK_SIZE
+*
+* DESCRIPTION
+* Size of a non-RMPP MAD datagram.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_SIZE 256
+/**********/
+
+/****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE
+* NAME
+* MAD_RMPP_HDR_SIZE
+*
+* DESCRIPTION
+* Size of an RMPP header, including the common MAD header.
+*
+* SOURCE
+*/
+#define MAD_RMPP_HDR_SIZE 36
+/**********/
+
+/****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE
+* NAME
+* MAD_RMPP_DATA_SIZE
+*
+* DESCRIPTION
+* Size of an RMPP transaction data section.
+*
+* SOURCE
+*/
+#define MAD_RMPP_DATA_SIZE (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE)
+/**********/
+
+/****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE
+* NAME
+* MAD_BLOCK_GRH_SIZE
+*
+* DESCRIPTION
+* Size of a MAD datagram, including the GRH.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_GRH_SIZE 296
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_PERMISSIVE
+* NAME
+* IB_LID_PERMISSIVE
+*
+* DESCRIPTION
+* Permissive LID
+*
+* SOURCE
+*/
+#define IB_LID_PERMISSIVE 0xFFFF
+/**********/
+
+/****d* IBA Base: Constants/IB_DEFAULT_PKEY
+* NAME
+* IB_DEFAULT_PKEY
+*
+* DESCRIPTION
+* P_Key value for the default partition.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_PKEY 0xFFFF
+/**********/
+
+/****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY
+* NAME
+* IB_QP1_WELL_KNOWN_Q_KEY
+*
+* DESCRIPTION
+* Well-known Q_Key for QP1 privileged mode access (15.4.2).
+*
+* SOURCE
+*/
+#define IB_QP1_WELL_KNOWN_Q_KEY CL_NTOH32(0x80010000)
+/*********/
+
+#define IB_QP0 0
+#define IB_QP1 CL_NTOH32(1)
+
+#define IB_QP_PRIVILEGED_Q_KEY CL_NTOH32(0x80000000)
+
+/****d* IBA Base: Constants/IB_LID_UCAST_START
+* NAME
+* IB_LID_UCAST_START
+*
+* DESCRIPTION
+* Lowest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_START_HO 0x0001
+#define IB_LID_UCAST_START (CL_HTON16(IB_LID_UCAST_START_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_UCAST_END
+* NAME
+* IB_LID_UCAST_END
+*
+* DESCRIPTION
+* Highest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_END_HO 0xBFFF
+#define IB_LID_UCAST_END (CL_HTON16(IB_LID_UCAST_END_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_MCAST_START
+* NAME
+* IB_LID_MCAST_START
+*
+* DESCRIPTION
+* Lowest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_START_HO 0xC000
+#define IB_LID_MCAST_START (CL_HTON16(IB_LID_MCAST_START_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_MCAST_END
+* NAME
+* IB_LID_MCAST_END
+*
+* DESCRIPTION
+* Highest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_END_HO 0xFFFE
+#define IB_LID_MCAST_END (CL_HTON16(IB_LID_MCAST_END_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX
+* NAME
+* IB_DEFAULT_SUBNET_PREFIX
+*
+* DESCRIPTION
+* Default subnet GID prefix.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_SUBNET_PREFIX (CL_HTON64(0xFE80000000000000ULL))
+/**********/
+
+/****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX
+* NAME
+* IB_NODE_NUM_PORTS_MAX
+*
+* DESCRIPTION
+* Maximum number of ports in a single node (14.2.5.7).
+* SOURCE
+*/
+#define IB_NODE_NUM_PORTS_MAX 0xFE
+/**********/
+
+/****d* IBA Base: Constants/IB_INVALID_PORT_NUM
+* NAME
+* IB_INVALID_PORT_NUM
+*
+* DESCRIPTION
+* Value used to indicate an invalid port number (14.2.5.10).
+*
+* SOURCE
+*/
+#define IB_INVALID_PORT_NUM 0xFF
+/*********/
+
+/****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX
+* NAME
+* IB_SUBNET_PATH_HOPS_MAX
+*
+* DESCRIPTION
+* Maximum number of directed route switch hops in a subnet (14.2.1.2).
+*
+* SOURCE
+*/
+#define IB_SUBNET_PATH_HOPS_MAX 64
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS
+* NAME
+* IB_PKEY_MAX_BLOCKS
+*
+* DESCRIPTION
+* Maximum number of PKEY blocks (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_MAX_BLOCKS 2048
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID
+* NAME
+* IB_MCAST_MAX_BLOCK_ID
+*
+* DESCRIPTION
+* Maximum number of Multicast port mask blocks
+*
+* SOURCE
+*/
+#define IB_MCAST_MAX_BLOCK_ID 511
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO
+* NAME
+* IB_MCAST_BLOCK_ID_MASK_HO
+*
+* DESCRIPTION
+* Mask (host order) to recover the Multicast block ID.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_ID_MASK_HO 0x000001FF
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE
+* NAME
+* IB_MCAST_BLOCK_SIZE
+*
+* DESCRIPTION
+* Number of port mask entries in a multicast forwarding table block.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_SIZE 32
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_MASK_SIZE
+* NAME
+* IB_MCAST_MASK_SIZE
+*
+* DESCRIPTION
+* Number of port mask bits in each entry in the multicast forwarding table.
+*
+* SOURCE
+*/
+#define IB_MCAST_MASK_SIZE 16
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO
+* NAME
+* IB_MCAST_POSITION_MASK_HO
+*
+* DESCRIPTION
+* Mask (host order) to recover the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MASK_HO 0xF0000000
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MAX
+* NAME
+* IB_MCAST_POSITION_MAX
+*
+* DESCRIPTION
+* Maximum value for the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MAX 0xF
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT
+* NAME
+* IB_MCAST_POSITION_SHIFT
+*
+* DESCRIPTION
+* Shift value to normalize the multicast block position value.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_SHIFT 28
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX
+* NAME
+* IB_PKEY_ENTRIES_MAX
+*
+* DESCRIPTION
+* Maximum number of PKEY entries per port (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK)
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_BASE_MASK
+* NAME
+* IB_PKEY_BASE_MASK
+*
+* DESCRIPTION
+* Masks for the base P_Key value given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_BASE_MASK (CL_NTOH16(0x7FFF))
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_TYPE_MASK
+* NAME
+* IB_PKEY_TYPE_MASK
+*
+* DESCRIPTION
+* Masks for the P_Key membership type given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_TYPE_MASK (CL_NTOH16(0x8000))
+/*********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_LID
+* NAME
+* IB_MCLASS_SUBN_LID
+*
+* DESCRIPTION
+* Subnet Management Class, Subnet Manager LID routed (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_LID 0x01
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR
+* NAME
+* IB_MCLASS_SUBN_DIR
+*
+* DESCRIPTION
+* Subnet Management Class, Subnet Manager directed route (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_DIR 0x81
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM
+* NAME
+* IB_MCLASS_SUBN_ADM
+*
+* DESCRIPTION
+* Subnet Management Class, Subnet Administration (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_ADM 0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_PERF
+* NAME
+* IB_MCLASS_PERF
+*
+* DESCRIPTION
+* Subnet Management Class, Performance Manager (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_PERF 0x04
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_BM
+* NAME
+* IB_MCLASS_BM
+*
+* DESCRIPTION
+* Subnet Management Class, Baseboard Manager (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_BM 0x05
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT
+* NAME
+* IB_MCLASS_DEV_MGMT
+*
+* DESCRIPTION
+* Subnet Management Class, Device Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_DEV_MGMT 0x06
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT
+* NAME
+* IB_MCLASS_COMM_MGMT
+*
+* DESCRIPTION
+* Subnet Management Class, Communication Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_COMM_MGMT 0x07
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SNMP
+* NAME
+* IB_MCLASS_SNMP
+*
+* DESCRIPTION
+* Subnet Management Class, SNMP Tunneling (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SNMP 0x08
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN
+* NAME
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN
+*
+* DESCRIPTION
+* Subnet Management Class, Vendor Specific Low Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX
+* NAME
+* IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*
+* DESCRIPTION
+* Subnet Management Class, Vendor Specific Low Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0f
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+* NAME
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+*
+* DESCRIPTION
+* Subnet Management Class, Vendor Specific High Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+* NAME
+* IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*
+* DESCRIPTION
+* Subnet Management Class, Vendor Specific High Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4f
+/**********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific_low
+* NAME
+* ib_class_is_vendor_specific_low
+*
+* DESCRIPTION
+* Indicitates if the Class Code if a vendor specific class from
+* the low range
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_class_is_vendor_specific_low(
+ IN const uint8_t class_code )
+{
+ return( (class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) &&
+ (class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX)) ;
+}
+/*
+* PARAMETERS
+* class_code
+* [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+* TRUE if the class is in the Low range of Vendor Specific MADs
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific_high
+* NAME
+* ib_class_is_vendor_specific_high
+*
+* DESCRIPTION
+* Indicitates if the Class Code if a vendor specific class from
+* the high range
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_class_is_vendor_specific_high(
+ IN const uint8_t class_code )
+{
+ return( (class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) &&
+ (class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX)) ;
+}
+/*
+* PARAMETERS
+* class_code
+* [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+* TRUE if the class is in the High range of Vendor Specific MADs
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*********/
+
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific
+* NAME
+* ib_class_is_vendor_specific
+*
+* DESCRIPTION
+* Indicitates if the Class Code if a vendor specific class
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_class_is_vendor_specific(
+ IN const uint8_t class_code )
+{
+ return( ib_class_is_vendor_specific_low(class_code) ||
+ ib_class_is_vendor_specific_high(class_code) );
+}
+/*
+* PARAMETERS
+* class_code
+* [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+* TRUE if the class is a Vendor Specific MAD
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high
+*********/
+
+/*
+ * MAD methods
+ */
+/****d* IBA Base: Constants/IB_MAX_METHOD
+* NAME
+* IB_MAX_METHOD
+*
+* DESCRIPTION
+* Total number of methods available to a class, not including the R-bit.
+*
+* SOURCE
+*/
+#define IB_MAX_METHODS 128
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK
+* NAME
+* IB_MAD_METHOD_RESP_MASK
+*
+* DESCRIPTION
+* Response mask to extract 'R' bit from the method field. (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_RESP_MASK 0x80
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET
+* NAME
+* IB_MAD_METHOD_GET
+*
+* DESCRIPTION
+* Get() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET 0x01
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_SET
+* NAME
+* IB_MAD_METHOD_SET
+*
+* DESCRIPTION
+* Set() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SET 0x02
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP
+* NAME
+* IB_MAD_METHOD_GET_RESP
+*
+* DESCRIPTION
+* GetResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET_RESP 0x81
+/**********/
+
+#define IB_MAD_METHOD_DELETE 0x15
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE
+* NAME
+* IB_MAD_METHOD_GETTABLE
+*
+* DESCRIPTION
+* SubnAdmGetTable() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE 0x12
+
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP
+* NAME
+* IB_MAD_METHOD_GETTABLE_RESP
+*
+* DESCRIPTION
+* SubnAdmGetTableResp() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE_RESP 0x92
+
+/**********/
+
+#define IB_MAD_METHOD_GETTRACETABLE 0x13
+#define IB_MAD_METHOD_GETMULTI 0x14
+#define IB_MAD_METHOD_GETMULTI_RESP 0x94
+
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_SEND
+* NAME
+* IB_MAD_METHOD_SEND
+*
+* DESCRIPTION
+* Send() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SEND 0x03
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP
+* NAME
+* IB_MAD_METHOD_TRAP
+*
+* DESCRIPTION
+* Trap() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP 0x05
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT
+* NAME
+* IB_MAD_METHOD_REPORT
+*
+* DESCRIPTION
+* Report() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT 0x06
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP
+* NAME
+* IB_MAD_METHOD_REPORT_RESP
+*
+* DESCRIPTION
+* ReportResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT_RESP 0x86
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS
+* NAME
+* IB_MAD_METHOD_TRAP_REPRESS
+*
+* DESCRIPTION
+* TrapRepress() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP_REPRESS 0x07
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_BUSY
+* NAME
+* IB_MAD_STATUS_BUSY
+*
+* DESCRIPTION
+* Temporarily busy, MAD discarded (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_BUSY (CL_HTON16(0x0001))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT
+* NAME
+* IB_MAD_STATUS_REDIRECT
+*
+* DESCRIPTION
+* QP Redirection required (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_REDIRECT (CL_HTON16(0x0002))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER
+* NAME
+* IB_MAD_STATUS_UNSUP_CLASS_VER
+*
+* DESCRIPTION
+* Unsupported class version (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_CLASS_VER (CL_HTON16(0x0004))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD
+* NAME
+* IB_MAD_STATUS_UNSUP_METHOD
+*
+* DESCRIPTION
+* Unsupported method (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD (CL_HTON16(0x0008))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR
+* NAME
+* IB_MAD_STATUS_UNSUP_METHOD_ATTR
+*
+* DESCRIPTION
+* Unsupported method/attribute combination (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD_ATTR (CL_HTON16(0x000C))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD
+* NAME
+* IB_MAD_STATUS_INVALID_FIELD
+*
+* DESCRIPTION
+* Attribute contains one or more invalid fields (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_INVALID_FIELD (CL_HTON16(0x001C))
+/**********/
+
+#define IB_MAD_STATUS_CLASS_MASK (CL_HTON16(0xFF00))
+
+#define IB_SA_MAD_STATUS_SUCCESS (CL_HTON16(0x0000))
+#define IB_SA_MAD_STATUS_NO_RESOURCES (CL_HTON16(0x0100))
+#define IB_SA_MAD_STATUS_REQ_INVALID (CL_HTON16(0x0200))
+#define IB_SA_MAD_STATUS_NO_RECORDS (CL_HTON16(0x0300))
+#define IB_SA_MAD_STATUS_TOO_MANY_RECORDS (CL_HTON16(0x0400))
+#define IB_SA_MAD_STATUS_INVALID_GID (CL_HTON16(0x0500))
+#define IB_SA_MAD_STATUS_INSUF_COMPS (CL_HTON16(0x0600))
+
+#define IB_DM_MAD_STATUS_NO_IOC_RESP (CL_HTON16(0x0100))
+#define IB_DM_MAD_STATUS_NO_SVC_ENTRIES (CL_HTON16(0x0200))
+#define IB_DM_MAD_STATUS_IOC_FAILURE (CL_HTON16(0x8000))
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO
+* NAME
+* IB_MAD_ATTR_CLASS_PORT_INFO
+*
+* DESCRIPTION
+* ClassPortInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_CLASS_PORT_INFO (CL_NTOH16(0x0001))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE
+* NAME
+* IB_MAD_ATTR_NOTICE
+*
+* DESCRIPTION
+* Notice attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NOTICE (CL_NTOH16(0x0002))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO
+* NAME
+* IB_MAD_ATTR_INFORM_INFO
+*
+* DESCRIPTION
+* InformInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_INFORM_INFO (CL_NTOH16(0x0003))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC
+* NAME
+* IB_MAD_ATTR_NODE_DESC
+*
+* DESCRIPTION
+* NodeDescription attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_DESC (CL_NTOH16(0x0010))
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL
+* NAME
+* IB_MAD_ATTR_PORT_SMPL_CTRL
+*
+* DESCRIPTION
+* NodeDescription attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_CTRL (CL_NTOH16(0x0010))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO
+* NAME
+* IB_MAD_ATTR_NODE_INFO
+*
+* DESCRIPTION
+* NodeInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_INFO (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT
+* NAME
+* IB_MAD_ATTR_PORT_SMPL_RSLT
+*
+* DESCRIPTION
+* NodeInfo attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_RSLT (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO
+* NAME
+* IB_MAD_ATTR_SWITCH_INFO
+*
+* DESCRIPTION
+* SwitchInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SWITCH_INFO (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS
+* NAME
+* IB_MAD_ATTR_PORT_CNTRS
+*
+* DESCRIPTION
+* SwitchInfo attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_CNTRS (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO
+* NAME
+* IB_MAD_ATTR_GUID_INFO
+*
+* DESCRIPTION
+* GUIDInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_GUID_INFO (CL_NTOH16(0x0014))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO
+* NAME
+* IB_MAD_ATTR_PORT_INFO
+*
+* DESCRIPTION
+* PortInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_INFO (CL_NTOH16(0x0015))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE
+* NAME
+* IB_MAD_ATTR_P_KEY_TABLE
+*
+* DESCRIPTION
+* PartitionTable attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_P_KEY_TABLE (CL_NTOH16(0x0016))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE
+* NAME
+* IB_MAD_ATTR_SLVL_TABLE
+*
+* DESCRIPTION
+* SL VL Mapping Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_TABLE (CL_NTOH16(0x0017))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION
+* NAME
+* IB_MAD_ATTR_VL_ARBITRATION
+*
+* DESCRIPTION
+* VL Arbitration Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VL_ARBITRATION (CL_NTOH16(0x0018))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL
+* NAME
+* IB_MAD_ATTR_LIN_FWD_TBL
+*
+* DESCRIPTION
+* Switch linear forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LIN_FWD_TBL (CL_NTOH16(0x0019))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL
+* NAME
+* IB_MAD_ATTR_RND_FWD_TBL
+*
+* DESCRIPTION
+* Switch random forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_RND_FWD_TBL (CL_NTOH16(0x001A))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL
+* NAME
+* IB_MAD_ATTR_MCAST_FWD_TBL
+*
+* DESCRIPTION
+* Switch multicast forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCAST_FWD_TBL (CL_NTOH16(0x001B))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD
+* NAME
+* IB_MAD_ATTR_NODE_RECORD
+*
+* DESCRIPTION
+* NodeRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_RECORD (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD
+* NAME
+* IB_MAD_ATTR_PORTINFO_RECORD
+*
+* DESCRIPTION
+* PortInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORTINFO_RECORD (CL_NTOH16(0x0012))
+/**********/
+
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD
+* NAME
+* IB_MAD_ATTR_LINK_RECORD
+*
+* DESCRIPTION
+* LinkRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LINK_RECORD (CL_NTOH16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO
+* NAME
+* IB_MAD_ATTR_SM_INFO
+*
+* DESCRIPTION
+* SMInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SM_INFO (CL_NTOH16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD
+* NAME
+* IB_MAD_ATTR_SMINFO_RECORD
+*
+* DESCRIPTION
+* SmInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SMINFO_RECORD (CL_NTOH16(0x0018))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG
+* NAME
+* IB_MAD_ATTR_VENDOR_DIAG
+*
+* DESCRIPTION
+* VendorDiag attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VENDOR_DIAG (CL_NTOH16(0x0030))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO
+* NAME
+* IB_MAD_ATTR_LED_INFO
+*
+* DESCRIPTION
+* LedInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LED_INFO (CL_NTOH16(0x0031))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD
+* NAME
+* IB_MAD_ATTR_SERVICE_RECORD
+*
+* DESCRIPTION
+* ServiceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_RECORD (CL_NTOH16(0x0031))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD
+* NAME
+* IB_MAD_ATTR_LFT_RECORD
+*
+* DESCRIPTION
+* LinearForwardingRecord attribute (15.2.5.6)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LFT_RECORD (CL_NTOH16(0x0015))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD
+* NAME
+* IB_MAD_ATTR_PKEYTBL_RECORD
+*
+* DESCRIPTION
+* P-KEY table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PKEY_TBL_RECORD (CL_NTOH16(0x0033))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD
+* NAME
+* IB_MAD_ATTR_PATH_RECORD
+*
+* DESCRIPTION
+* PathRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PATH_RECORD (CL_NTOH16(0x0035))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD
+* NAME
+* IB_MAD_ATTR_VLARB_RECORD
+*
+* DESCRIPTION
+* VL Arbitration Table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VLARB_RECORD (CL_NTOH16(0x0036))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD
+* NAME
+* IB_MAD_ATTR_SLVL_RECORD
+*
+* DESCRIPTION
+* VSLtoL Map Table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_RECORD (CL_NTOH16(0x0013))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD
+* NAME
+* IB_MAD_ATTR_MCMEMBER_RECORD
+*
+* DESCRIPTION
+* MCMemberRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCMEMBER_RECORD (CL_NTOH16(0x0038))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD
+* NAME
+* IB_MAD_ATTR_MTRACE_RECORD
+*
+* DESCRIPTION
+* TraceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TRACE_RECORD (CL_NTOH16(0x0039))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD
+* NAME
+* IB_MAD_ATTR_MULTIPATH_RECORD
+*
+* DESCRIPTION
+* MultiPath attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MULTIPATH_RECORD (CL_NTOH16(0x003A))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+* IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+* Service Association attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_NTOH16(0x003B))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO
+* NAME
+* IB_MAD_ATTR_IO_UNIT_INFO
+*
+* DESCRIPTION
+* IOUnitInfo attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_UNIT_INFO (CL_NTOH16(0x0010))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+* NAME
+* IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+*
+* DESCRIPTION
+* IOControllerProfile attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_CONTROLLER_PROFILE (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES
+* NAME
+* IB_MAD_ATTR_SERVICE_ENTRIES
+*
+* DESCRIPTION
+* ServiceEntries attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_ENTRIES (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+* NAME
+* IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+*
+* DESCRIPTION
+* DiagnosticTimeout attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT (CL_NTOH16(0x0020))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST
+* NAME
+* IB_MAD_ATTR_PREPARE_TO_TEST
+*
+* DESCRIPTION
+* PrepareToTest attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PREPARE_TO_TEST (CL_NTOH16(0x0021))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE
+* NAME
+* IB_MAD_ATTR_TEST_DEVICE_ONCE
+*
+* DESCRIPTION
+* TestDeviceOnce attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_ONCE (CL_NTOH16(0x0022))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP
+* NAME
+* IB_MAD_ATTR_TEST_DEVICE_LOOP
+*
+* DESCRIPTION
+* TestDeviceLoop attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_LOOP (CL_NTOH16(0x0023))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE
+* NAME
+* IB_MAD_ATTR_DIAG_CODE
+*
+* DESCRIPTION
+* DiagCode attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAG_CODE (CL_NTOH16(0x0024))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+* IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+* Service Association attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_NTOH16(0x003B))
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_CA
+* NAME
+* IB_NODE_TYPE_CA
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_CA 0x01
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH
+* NAME
+* IB_NODE_TYPE_SWITCH
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_SWITCH 0x02
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER
+* NAME
+* IB_NODE_TYPE_ROUTER
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_ROUTER 0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_CA
+* NAME
+* IB_NOTICE_NODE_TYPE_CA
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_CA (CL_NTOH32(0x000001))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SWITCH
+* NAME
+* IB_NOTICE_NODE_TYPE_SWITCH
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_SWITCH (CL_NTOH32(0x000002))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_ROUTER
+* NAME
+* IB_NOTICE_NODE_TYPE_ROUTER
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_ROUTER (CL_NTOH32(0x000003))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SUBN_MGMT
+* NAME
+* IB_NOTICE_NODE_TYPE_SUBN_MGMT
+*
+* DESCRIPTION
+* Encoded generic node type used in MAD attributes (13.4.8.2).
+* Note that this value is not defined for the NodeType field
+* of the NodeInfo attribute (14.2.5.3).
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_SUBN_MGMT (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_MTU_LEN_TYPE
+* NAME
+* IB_MTU_LEN_TYPE
+*
+* DESCRIPTION
+* Encoded path MTU.
+* 1: 256
+* 2: 512
+* 3: 1024
+* 4: 2048
+* 5: 4096
+* others: reserved
+*
+* SOURCE
+*/
+#define IB_MTU_LEN_256 1
+#define IB_MTU_LEN_512 2
+#define IB_MTU_LEN_1024 3
+#define IB_MTU_LEN_2048 4
+#define IB_MTU_LEN_4096 5
+#define IB_MAX_MTU 5
+/**********/
+
+/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE
+* NAME
+* IB_PATH_SELECTOR_TYPE
+*
+* DESCRIPTION
+* Path selector.
+* 0: greater than rate specified
+* 1: less than rate specified
+* 2: exactly the rate specified
+* 3: largest rate available
+*
+* SOURCE
+*/
+#define IB_PATH_SELECTOR_GREATER_THAN 0
+#define IB_PATH_SELECTOR_LESS_THAN 1
+#define IB_PATH_SELECTOR_EXACTLY 2
+#define IB_PATH_SELECTOR_LARGEST 3
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE
+* NAME
+* IB_SMINFO_STATE_NOTACTIVE
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_NOTACTIVE 0
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING
+* NAME
+* IB_SMINFO_STATE_DISCOVERING
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_DISCOVERING 1
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY
+* NAME
+* IB_SMINFO_STATE_STANDBY
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_STANDBY 2
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER
+* NAME
+* IB_SMINFO_STATE_MASTER
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_MASTER 3
+/**********/
+/****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK
+* NAME
+* IB_PATH_REC_SELECTOR_MASK
+*
+* DESCRIPTION
+* Mask for the selector field for path record MTU, rate
+* and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_SELECTOR_MASK 0xC0
+/**********/
+/****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK
+* NAME
+* IB_PATH_REC_BASE_MASK
+*
+* DESCRIPTION
+* Mask for the base value field for path record MTU, rate
+* and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_BASE_MASK 0x3F
+/**********/
+
+/****h* IBA Base/Type Definitions
+* NAME
+* Type Definitions
+*
+* DESCRIPTION
+* Definitions are from the InfiniBand Architecture Specification v1.1
+*
+*********/
+/****d* IBA Base: Types/ib_net16_t
+* NAME
+* ib_net16_t
+*
+* DESCRIPTION
+* Defines the network ordered type for 16-bit values.
+*
+* SOURCE
+*/
+typedef uint16_t ib_net16_t;
+/**********/
+/****d* IBA Base: Types/ib_net32_t
+* NAME
+* ib_net32_t
+*
+* DESCRIPTION
+* Defines the network ordered type for 32-bit values.
+*
+* SOURCE
+*/
+typedef uint32_t ib_net32_t;
+/**********/
+/****d* IBA Base: Types/ib_net64_t
+* NAME
+* ib_net64_t
+*
+* DESCRIPTION
+* Defines the network ordered type for 64-bit values.
+*
+* SOURCE
+*/
+typedef uint64_t ib_net64_t;
+/**********/
+/****d* IBA Base: Types/ib_gid_prefix_t
+* NAME
+* ib_gid_prefix_t
+*
+* DESCRIPTION
+*
+* SOURCE
+*/
+typedef ib_net64_t ib_gid_prefix_t;
+/**********/
+
+/****d* IBA Base: Constants/ib_link_states_t
+* NAME
+* ib_link_states_t
+*
+* DESCRIPTION
+* Defines the link states of a port.
+*
+* SOURCE
+*/
+#define IB_LINK_NO_CHANGE 0
+#define IB_LINK_DOWN 1
+#define IB_LINK_INIT 2
+#define IB_LINK_ARMED 3
+#define IB_LINK_ACTIVE 4
+#define IB_LINK_ACT_DEFER 5
+/**********/
+
+static const char* const __ib_node_type_str[] =
+{
+ "UNKNOWN",
+ "Channel Adapter",
+ "Switch",
+ "Router",
+ "Subnet Management"
+};
+
+/****f* IBA Base: Types/ib_get_node_type_str
+* NAME
+* ib_get_node_type_str
+*
+* DESCRIPTION
+* Returns a string for the specified node type.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char* AL_API
+ib_get_node_type_str(
+ IN uint32_t node_type )
+{
+ if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )
+ node_type = 0;
+ return( __ib_node_type_str[node_type] );
+}
+/*
+* PARAMETERS
+* node_type
+* [in] Encoded node type as returned in the NodeInfo attribute.
+
+* RETURN VALUES
+* Pointer to the node type string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_node_info_t
+*********/
+
+static const char* const __ib_port_state_str[] =
+{
+ "No State Change (NOP)",
+ "DOWN",
+ "INIT",
+ "ARMED",
+ "ACTIVE",
+ "ACTDEFER",
+ "UNKNOWN"
+};
+
+/****f* IBA Base: Types/ib_get_port_state_str
+* NAME
+* ib_get_port_state_str
+*
+* DESCRIPTION
+* Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char* AL_API
+ib_get_port_state_str(
+ IN uint8_t port_state )
+{
+ if( port_state > IB_LINK_ACTIVE )
+ port_state = IB_LINK_ACTIVE + 1;
+ return( __ib_port_state_str[port_state] );
+}
+/*
+* PARAMETERS
+* node_type
+* [in] Encoded port state as returned in the PortInfo attribute.
+
+* RETURN VALUES
+* Pointer to the port state string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_get_port_state_from_str
+* NAME
+* ib_get_port_state_from_str
+*
+* DESCRIPTION
+* Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_get_port_state_from_str(
+ IN char* p_port_state_str )
+{
+ if( !strncmp(p_port_state_str,"No State Change (NOP)",12) )
+ return(0);
+ else if( !strncmp(p_port_state_str, "DOWN",4) )
+ return(1);
+ else if( !strncmp(p_port_state_str, "INIT", 4) )
+ return(2);
+ else if( !strncmp(p_port_state_str,"ARMED" , 5) )
+ return(3);
+ else if( !strncmp(p_port_state_str, "ACTIVE", 6) )
+ return(4);
+ else if( !strncmp(p_port_state_str, "ACTDEFER", 8) )
+ return(5);
+ return(6);
+}
+/*
+* PARAMETERS
+* p_port_state_str
+* [in] A string matching one returned by ib_get_port_state_str
+*
+* RETURN VALUES
+* The appropriate code.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_port_info_t
+*********/
+
+/****d* IBA Base: Constants/Join States
+* NAME
+* Join States
+*
+* DESCRIPTION
+* Defines the join state flags for multicast group management.
+*
+* SOURCE
+*/
+#define IB_JOIN_STATE_FULL 1
+#define IB_JOIN_STATE_NON 2
+#define IB_JOIN_STATE_SEND_ONLY 4
+/**********/
+
+/****f* IBA Base: Types/ib_pkey_get_base
+* NAME
+* ib_pkey_get_base
+*
+* DESCRIPTION
+* Returns the base P_Key value with the membership bit stripped.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net16_t AL_API
+ib_pkey_get_base(
+ IN const ib_net16_t pkey )
+{
+ return( (ib_net16_t)(pkey & IB_PKEY_BASE_MASK) );
+}
+/*
+* PARAMETERS
+* pkey
+* [in] P_Key value
+*
+* RETURN VALUE
+* Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_pkey_is_full_member
+* NAME
+* ib_pkey_is_full_member
+*
+* DESCRIPTION
+* Indicitates if the port is a full member of the parition.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_pkey_is_full_member(
+ IN const ib_net16_t pkey )
+{
+ return( (pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK );
+}
+/*
+* PARAMETERS
+* pkey
+* [in] P_Key value
+*
+* RETURN VALUE
+* TRUE if the port is a full member of the partition.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_pkey_get_base, ib_net16_t
+*********/
+
+/****f* IBA Base: Types/ib_pkey_is_invalid
+* NAME
+* ib_pkey_is_invalid
+*
+* DESCRIPTION
+* Returns TRUE if the given P_Key is an invalid P_Key
+* C10-116: the CI shall regard a P_Key as invalid if its low-order
+* 15 bits are all zero...
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t AL_API
+ib_pkey_is_invalid(
+ IN const ib_net16_t pkey )
+{
+ if (ib_pkey_get_base(pkey) == 0x0000)
+ return TRUE;
+
+ return FALSE;
+}
+/*
+* PARAMETERS
+* pkey
+* [in] P_Key value
+*
+* RETURN VALUE
+* Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* IBA Base: Types/ib_gid_t
+* NAME
+* ib_gid_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef union _ib_gid
+{
+ uint8_t raw[16];
+ struct _ib_gid_unicast
+ {
+ ib_gid_prefix_t prefix;
+ ib_net64_t interface_id;
+
+ } PACK_SUFFIX unicast;
+
+ struct _ib_gid_multicast
+ {
+ uint8_t header[2];
+ uint8_t raw_group_id[14];
+
+ } PACK_SUFFIX multicast;
+
+} PACK_SUFFIX ib_gid_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* raw
+* GID represented as an unformated byte array.
+*
+* unicast
+* Typical unicast representation with subnet prefix and
+* port GUID.
+*
+* multicast
+* Representation for multicast use.
+*
+* SEE ALSO
+*********/
+
+AL_INLINE boolean_t AL_API
+ib_gid_is_multicast(
+ IN const ib_gid_t* p_gid )
+{
+ return( p_gid->raw[0] == 0xFF );
+}
+
+/****f* IBA Base: Types/ib_gid_set_default
+* NAME
+* ib_gid_set_default
+*
+* DESCRIPTION
+* Sets a GID to the default value.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_gid_set_default(
+ IN ib_gid_t* const p_gid,
+ IN const ib_net64_t interface_id )
+{
+ p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;
+ p_gid->unicast.interface_id = interface_id;
+}
+/*
+* PARAMETERS
+* p_gid
+* [in] Pointer to the GID object.
+*
+* interface_id
+* [in] Manufacturer assigned EUI64 value of a port.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_get_subnet_prefix
+* NAME
+* ib_gid_get_subnet_prefix
+*
+* DESCRIPTION
+* Gets the subnet prefix from a GID.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net64_t AL_API
+ib_gid_get_subnet_prefix(
+ IN const ib_gid_t* const p_gid )
+{
+ return( p_gid->unicast.prefix );
+}
+/*
+* PARAMETERS
+* p_gid
+* [in] Pointer to the GID object.
+*
+* RETURN VALUES
+* 64-bit subnet prefix value.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_is_link_local
+* NAME
+* ib_gid_is_link_local
+*
+* DESCRIPTION
+* Returns TRUE if the unicast GID scoping indicates link local,
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_gid_is_link_local(
+ IN const ib_gid_t* const p_gid )
+{
+ return( ib_gid_get_subnet_prefix( p_gid ) == IB_DEFAULT_SUBNET_PREFIX );
+}
+/*
+* PARAMETERS
+* p_gid
+* [in] Pointer to the GID object.
+*
+* RETURN VALUES
+* Returns TRUE if the unicast GID scoping indicates link local,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_is_site_local
+* NAME
+* ib_gid_is_site_local
+*
+* DESCRIPTION
+* Returns TRUE if the unicast GID scoping indicates site local,
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_gid_is_site_local(
+ IN const ib_gid_t* const p_gid )
+{
+ return( ( ib_gid_get_subnet_prefix( p_gid ) &
+ CL_HTON64( 0xFFFFFFFFFFFF0000ULL ) ) == CL_HTON64( 0xFEC0000000000000ULL ) );
+}
+/*
+* PARAMETERS
+* p_gid
+* [in] Pointer to the GID object.
+*
+* RETURN VALUES
+* Returns TRUE if the unicast GID scoping indicates link local,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_get_guid
+* NAME
+* ib_gid_get_guid
+*
+* DESCRIPTION
+* Gets the guid from a GID.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net64_t AL_API
+ib_gid_get_guid(
+ IN const ib_gid_t* const p_gid )
+{
+ return( p_gid->unicast.interface_id );
+}
+/*
+* PARAMETERS
+* p_gid
+* [in] Pointer to the GID object.
+*
+* RETURN VALUES
+* 64-bit GUID value.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+
+/****s* IBA Base: Types/ib_path_rec_t
+* NAME
+* ib_path_rec_t
+*
+* DESCRIPTION
+* Path records encapsulate the properties of a given
+* route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_path_rec
+{
+ uint8_t resv0[8];
+ ib_gid_t dgid;
+ ib_gid_t sgid;
+ ib_net16_t dlid;
+ ib_net16_t slid;
+ ib_net32_t hop_flow_raw;
+ uint8_t tclass;
+ uint8_t num_path;
+ ib_net16_t pkey;
+ ib_net16_t sl;
+ uint8_t mtu;
+ uint8_t rate;
+ uint8_t pkt_life;
+ uint8_t preference;
+ uint8_t resv2[6];
+
+} PACK_SUFFIX ib_path_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* resv0
+* Reserved bytes.
+*
+* dgid
+* GID of destination port.
+*
+* sgid
+* GID of source port.
+*
+* dlid
+* LID of destination port.
+*
+* slid
+* LID of source port.
+*
+* hop_flow_raw
+* Global routing parameters: hop count, flow label and raw bit.
+*
+* tclass
+* Another global routing parameter.
+*
+* num_path
+* Reversible path - 1 bit to say if path is reversible.
+* Num-Paths [6:0] In queries, maximum number of paths to return.
+* In responses, undefined.
+*
+* pkey
+* Partition key (P_Key) to use on this path.
+*
+* resv1
+* Reserved byte.
+*
+* sl
+* Service level to use on this path.
+*
+* mtu
+* MTU and MTU selector fields to use on this path
+*
+* rate
+* Rate and rate selector fields to use on this path.
+*
+* pkt_life
+* Packet lifetime
+*
+* preference
+* Indicates the relative merit of this path versus other path
+* records returned from the SA. Lower numbers are better.
+*
+* resv2
+* Reserved bytes.
+* SEE ALSO
+*********/
+
+/* Path Record Component Masks */
+#define IB_PR_COMPMASK_DGID (CL_HTON64(((uint64_t)1)<<2))
+#define IB_PR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<3))
+#define IB_PR_COMPMASK_DLID (CL_HTON64(((uint64_t)1)<<4))
+#define IB_PR_COMPMASK_SLID (CL_HTON64(((uint64_t)1)<<5))
+#define IB_PR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<6))
+#define IB_PR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<7))
+#define IB_PR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<8))
+#define IB_PR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<9))
+#define IB_PR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<10))
+#define IB_PR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<11))
+#define IB_PR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<12))
+#define IB_PR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<13))
+#define IB_PR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<14))
+#define IB_PR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<15))
+#define IB_PR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<16))
+#define IB_PR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<17))
+#define IB_PR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<18))
+#define IB_PR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<19))
+#define IB_PR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<20))
+#define IB_PR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<21))
+
+/* Link Record Component Masks */
+#define IB_LR_COMPMASK_FROM_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LR_COMPMASK_FROM_PORT (CL_HTON64(((uint64_t)1)<<1))
+#define IB_LR_COMPMASK_TO_PORT (CL_HTON64(((uint64_t)1)<<2))
+#define IB_LR_COMPMASK_TO_LID (CL_HTON64(((uint64_t)1)<<3))
+
+/* VL Arbitration Record MASKs */
+#define IB_VLA_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_VLA_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<1))
+#define IB_VLA_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<2))
+/* SLtoVL Mapping Record Masks */
+#define IB_SLVL_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SLVL_COMPMASK_IN_PORT (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SLVL_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<2))
+/* P_Key Table Record Masks */
+#define IB_PKEY_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PKEY_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PKEY_COMPMASK_PORT (CL_HTON64(((uint64_t)1)<<2))
+/* LFT Record MASKS */
+#define IB_LFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1))
+/* ModeInfo Record MASKS */
+#define IB_NR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_NR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1))
+#define IB_NR_COMPMASK_BASEVERSION (CL_HTON64(((uint64_t)1)<<2))
+#define IB_NR_COMPMASK_CLASSVERSION (CL_HTON64(((uint64_t)1)<<3))
+#define IB_NR_COMPMASK_NODETYPE (CL_HTON64(((uint64_t)1)<<4))
+#define IB_NR_COMPMASK_NUMPORTS (CL_HTON64(((uint64_t)1)<<5))
+#define IB_NR_COMPMASK_SYSIMAGEGUID (CL_HTON64(((uint64_t)1)<<6))
+#define IB_NR_COMPMASK_NODEGUID (CL_HTON64(((uint64_t)1)<<7))
+#define IB_NR_COMPMASK_PORTGUID (CL_HTON64(((uint64_t)1)<<8))
+#define IB_NR_COMPMASK_PARTCAP (CL_HTON64(((uint64_t)1)<<9))
+#define IB_NR_COMPMASK_DEVID (CL_HTON64(((uint64_t)1)<<10))
+#define IB_NR_COMPMASK_REV (CL_HTON64(((uint64_t)1)<<11))
+#define IB_NR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<12))
+#define IB_NR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<13))
+#define IB_NR_COMPMASK_NODEDESC (CL_HTON64(((uint64_t)1)<<14))
+/* Service Record Component Mask Sec 15.2.5.14 Ver 1.1*/
+#define IB_SR_COMPMASK_SID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SR_COMPMASK_SPKEY (CL_HTON64(((uint64_t)1)<<2))
+#define IB_SR_COMPMASK_RES1 (CL_HTON64(((uint64_t)1)<<3))
+#define IB_SR_COMPMASK_SLEASE (CL_HTON64(((uint64_t)1)<<4))
+#define IB_SR_COMPMASK_SKEY (CL_HTON64(((uint64_t)1)<<5))
+#define IB_SR_COMPMASK_SNAME (CL_HTON64(((uint64_t)1)<<6))
+#define IB_SR_COMPMASK_SDATA8_0 (CL_HTON64(((uint64_t)1)<<7))
+#define IB_SR_COMPMASK_SDATA8_1 (CL_HTON64(((uint64_t)1)<<8))
+#define IB_SR_COMPMASK_SDATA8_2 (CL_HTON64(((uint64_t)1)<<9))
+#define IB_SR_COMPMASK_SDATA8_3 (CL_HTON64(((uint64_t)1)<<10))
+#define IB_SR_COMPMASK_SDATA8_4 (CL_HTON64(((uint64_t)1)<<11))
+#define IB_SR_COMPMASK_SDATA8_5 (CL_HTON64(((uint64_t)1)<<12))
+#define IB_SR_COMPMASK_SDATA8_6 (CL_HTON64(((uint64_t)1)<<13))
+#define IB_SR_COMPMASK_SDATA8_7 (CL_HTON64(((uint64_t)1)<<14))
+#define IB_SR_COMPMASK_SDATA8_8 (CL_HTON64(((uint64_t)1)<<15))
+#define IB_SR_COMPMASK_SDATA8_9 (CL_HTON64(((uint64_t)1)<<16))
+#define IB_SR_COMPMASK_SDATA8_10 (CL_HTON64(((uint64_t)1)<<17))
+#define IB_SR_COMPMASK_SDATA8_11 (CL_HTON64(((uint64_t)1)<<18))
+#define IB_SR_COMPMASK_SDATA8_12 (CL_HTON64(((uint64_t)1)<<19))
+#define IB_SR_COMPMASK_SDATA8_13 (CL_HTON64(((uint64_t)1)<<20))
+#define IB_SR_COMPMASK_SDATA8_14 (CL_HTON64(((uint64_t)1)<<21))
+#define IB_SR_COMPMASK_SDATA8_15 (CL_HTON64(((uint64_t)1)<<22))
+#define IB_SR_COMPMASK_SDATA16_0 (CL_HTON64(((uint64_t)1)<<23))
+#define IB_SR_COMPMASK_SDATA16_1 (CL_HTON64(((uint64_t)1)<<24))
+#define IB_SR_COMPMASK_SDATA16_2 (CL_HTON64(((uint64_t)1)<<25))
+#define IB_SR_COMPMASK_SDATA16_3 (CL_HTON64(((uint64_t)1)<<26))
+#define IB_SR_COMPMASK_SDATA16_4 (CL_HTON64(((uint64_t)1)<<27))
+#define IB_SR_COMPMASK_SDATA16_5 (CL_HTON64(((uint64_t)1)<<28))
+#define IB_SR_COMPMASK_SDATA16_6 (CL_HTON64(((uint64_t)1)<<29))
+#define IB_SR_COMPMASK_SDATA16_7 (CL_HTON64(((uint64_t)1)<<30))
+#define IB_SR_COMPMASK_SDATA32_0 (CL_HTON64(((uint64_t)1)<<31))
+#define IB_SR_COMPMASK_SDATA32_1 (CL_HTON64(((uint64_t)1)<<32))
+#define IB_SR_COMPMASK_SDATA32_2 (CL_HTON64(((uint64_t)1)<<33))
+#define IB_SR_COMPMASK_SDATA32_3 (CL_HTON64(((uint64_t)1)<<34))
+#define IB_SR_COMPMASK_SDATA64_0 (CL_HTON64(((uint64_t)1)<<35))
+#define IB_SR_COMPMASK_SDATA64_1 (CL_HTON64(((uint64_t)1)<<36))
+/* Port Info Record Component Masks */
+#define IB_PIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PIR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<2))
+#define IB_PIR_COMPMASK_MKEY (CL_HTON64(((uint64_t)1)<<3))
+#define IB_PIR_COMPMASK_GIDPRE (CL_HTON64(((uint64_t)1)<<4))
+#define IB_PIR_COMPMASK_BASELID (CL_HTON64(((uint64_t)1)<<5))
+#define IB_PIR_COMPMASK_SMLID (CL_HTON64(((uint64_t)1)<<6))
+#define IB_PIR_COMPMASK_CAPMASK (CL_HTON64(((uint64_t)1)<<7))
+#define IB_PIR_COMPMASK_DIAGCODE (CL_HTON64(((uint64_t)1)<<8))
+#define IB_PIR_COMPMASK_MKEYLEASEPRD (CL_HTON64(((uint64_t)1)<<9))
+#define IB_PIR_COMPMASK_LOCALPORTNUM (CL_HTON64(((uint64_t)1)<<10))
+#define IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11))
+#define IB_PIR_COMPMASK_LNKWIDTHSUPPORT (CL_HTON64(((uint64_t)1)<<12))
+#define IB_PIR_COMPMASK_LNKWIDTHACTIVE (CL_HTON64(((uint64_t)1)<<13))
+#define IB_PIR_COMPMASK_LNKSPEEDSUPPORT (CL_HTON64(((uint64_t)1)<<14))
+#define IB_PIR_COMPMASK_PORTSTATE (CL_HTON64(((uint64_t)1)<<15))
+#define IB_PIR_COMPMASK_PORTPHYSTATE (CL_HTON64(((uint64_t)1)<<16))
+#define IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17))
+#define IB_PIR_COMPMASK_MKEYPROTBITS (CL_HTON64(((uint64_t)1)<<18))
+#define IB_PIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<19))
+#define IB_PIR_COMPMASK_LMC (CL_HTON64(((uint64_t)1)<<20))
+#define IB_PIR_COMPMASK_LINKSPEEDACTIVE (CL_HTON64(((uint64_t)1)<<21))
+#define IB_PIR_COMPMASK_LINKSPEEDENABLE (CL_HTON64(((uint64_t)1)<<22))
+#define IB_PIR_COMPMASK_NEIGHBORMTU (CL_HTON64(((uint64_t)1)<<23))
+#define IB_PIR_COMPMASK_MASTERSMSL (CL_HTON64(((uint64_t)1)<<24))
+#define IB_PIR_COMPMASK_VLCAP (CL_HTON64(((uint64_t)1)<<25))
+#define IB_PIR_COMPMASK_INITTYPE (CL_HTON64(((uint64_t)1)<<26))
+#define IB_PIR_COMPMASK_VLHIGHLIMIT (CL_HTON64(((uint64_t)1)<<27))
+#define IB_PIR_COMPMASK_VLARBHIGHCAP (CL_HTON64(((uint64_t)1)<<28))
+#define IB_PIR_COMPMASK_VLARBLOWCAP (CL_HTON64(((uint64_t)1)<<29))
+#define IB_PIR_COMPMASK_INITTYPEREPLY (CL_HTON64(((uint64_t)1)<<30))
+#define IB_PIR_COMPMASK_MTUCAP (CL_HTON64(((uint64_t)1)<<31))
+#define IB_PIR_COMPMASK_VLSTALLCNT (CL_HTON64(((uint64_t)1)<<32))
+#define IB_PIR_COMPMASK_HOQLIFE (CL_HTON64(((uint64_t)1)<<33))
+#define IB_PIR_COMPMASK_OPVLS (CL_HTON64(((uint64_t)1)<<34))
+#define IB_PIR_COMPMASK_PARENFIN (CL_HTON64(((uint64_t)1)<<35))
+#define IB_PIR_COMPMASK_PARENFOUT (CL_HTON64(((uint64_t)1)<<36))
+#define IB_PIR_COMPMASK_FILTERRAWIN (CL_HTON64(((uint64_t)1)<<37))
+#define IB_PIR_COMPMASK_FILTERRAWOUT (CL_HTON64(((uint64_t)1)<<38))
+#define IB_PIR_COMPMASK_MKEYVIO (CL_HTON64(((uint64_t)1)<<39))
+#define IB_PIR_COMPMASK_PKEYVIO (CL_HTON64(((uint64_t)1)<<40))
+#define IB_PIR_COMPMASK_QKEYVIO (CL_HTON64(((uint64_t)1)<<41))
+#define IB_PIR_COMPMASK_GUIDCAP (CL_HTON64(((uint64_t)1)<<42))
+#define IB_PIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<43))
+#define IB_PIR_COMPMASK_SUBNTO (CL_HTON64(((uint64_t)1)<<44))
+#define IB_PIR_COMPMASK_RESV4 (CL_HTON64(((uint64_t)1)<<45))
+#define IB_PIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<46))
+#define IB_PIR_COMPMASK_LOCALPHYERR (CL_HTON64(((uint64_t)1)<<47))
+#define IB_PIR_COMPMASK_OVERRUNERR (CL_HTON64(((uint64_t)1)<<48))
+/* Multicast Member Record Component Masks */
+#define IB_MCR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_MGID (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_PORT_GID (CL_HTON64(((uint64_t)1)<<1))
+#define IB_MCR_COMPMASK_QKEY (CL_HTON64(((uint64_t)1)<<2))
+#define IB_MCR_COMPMASK_MLID (CL_HTON64(((uint64_t)1)<<3))
+#define IB_MCR_COMPMASK_MTU_SEL (CL_HTON64(((uint64_t)1)<<4))
+#define IB_MCR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<5))
+#define IB_MCR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<6))
+#define IB_MCR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7))
+#define IB_MCR_COMPMASK_RATE_SEL (CL_HTON64(((uint64_t)1)<<8))
+#define IB_MCR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<9))
+#define IB_MCR_COMPMASK_LIFE_SEL (CL_HTON64(((uint64_t)1)<<10))
+#define IB_MCR_COMPMASK_LIFE (CL_HTON64(((uint64_t)1)<<11))
+#define IB_MCR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<12))
+#define IB_MCR_COMPMASK_FLOW (CL_HTON64(((uint64_t)1)<<13))
+#define IB_MCR_COMPMASK_HOP (CL_HTON64(((uint64_t)1)<<14))
+#define IB_MCR_COMPMASK_SCOPE (CL_HTON64(((uint64_t)1)<<15))
+#define IB_MCR_COMPMASK_JOIN_STATE (CL_HTON64(((uint64_t)1)<<16))
+#define IB_MCR_COMPMASK_PROXY (CL_HTON64(((uint64_t)1)<<17))
+
+/****f* IBA Base: Types/ib_path_rec_init_local
+* NAME
+* ib_path_rec_init_local
+*
+* DESCRIPTION
+* Initializes a subnet local path record.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_path_rec_init_local(
+ IN ib_path_rec_t* const p_rec,
+ IN ib_gid_t* const p_dgid,
+ IN ib_gid_t* const p_sgid,
+ IN ib_net16_t dlid,
+ IN ib_net16_t slid,
+ IN uint8_t num_path,
+ IN ib_net16_t pkey,
+ IN uint8_t sl,
+ IN uint8_t mtu_selector,
+ IN uint8_t mtu,
+ IN uint8_t rate_selector,
+ IN uint8_t rate,
+ IN uint8_t pkt_life_selector,
+ IN uint8_t pkt_life,
+ IN uint8_t preference )
+{
+ p_rec->dgid = *p_dgid;
+ p_rec->sgid = *p_sgid;
+ p_rec->dlid = dlid;
+ p_rec->slid = slid;
+ p_rec->num_path = num_path;
+ p_rec->pkey = pkey;
+ /* Lower 4 bits of path rec's SL are reserved. */
+ p_rec->sl = cl_ntoh16( sl );
+ p_rec->mtu = (uint8_t)((mtu & IB_PATH_REC_BASE_MASK) |
+ (uint8_t)(mtu_selector << 6));
+ p_rec->rate = (uint8_t)((rate & IB_PATH_REC_BASE_MASK) |
+ (uint8_t)(rate_selector << 6));
+ p_rec->pkt_life = (uint8_t)((pkt_life & IB_PATH_REC_BASE_MASK) |
+ (uint8_t)(pkt_life_selector << 6));
+ p_rec->preference = preference;
+
+ /* Clear global routing fields for local path records */
+ p_rec->hop_flow_raw = 0;
+ p_rec->tclass = 0;
+
+ *((uint64_t*)p_rec->resv0) = 0;
+ *((uint32_t*)p_rec->resv2) = 0;
+ *((uint16_t*)p_rec->resv2 + 2) = 0;
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* dgid
+* [in] GID of destination port.
+*
+* sgid
+* [in] GID of source port.
+*
+* dlid
+* [in] LID of destination port.
+*
+* slid
+* [in] LID of source port.
+*
+* num_path
+* [in] Reversible path - 1 bit to say if path is reversible.
+* Num-Paths [6:0] In queries, maximum number of paths to return.
+* In responses, undefined.
+*
+* pkey
+* [in] Partition key (P_Key) to use on this path.
+*
+* sl
+* [in] Service level to use on this path. Lower 4-bits are valid.
+*
+* mtu_selector
+* [in] Encoded MTU selector value to use on this path
+*
+* mtu
+* [in] Encoded MTU to use on this path
+*
+* rate_selector
+* [in] Encoded rate selector value to use on this path.
+*
+* rate
+* [in] Encoded rate to use on this path.
+*
+* pkt_life_selector
+* [in] Encoded Packet selector value lifetime for this path.
+*
+* pkt_life
+* [in] Encoded Packet lifetime for this path.
+*
+* preference
+* [in] Indicates the relative merit of this path versus other path
+* records returned from the SA. Lower numbers are better.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_num_path
+* NAME
+* ib_path_rec_num_path
+*
+* DESCRIPTION
+* Get max number of paths to return.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_num_path(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( p_rec->num_path &0x7F );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Maximum number of paths toreturn for each unique SGID_DGID combination.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_sl
+* NAME
+* ib_path_rec_sl
+*
+* DESCRIPTION
+* Get path service level.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_sl(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)((cl_ntoh16( p_rec->sl )) & 0xF) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path MTU.
+* 1: 256
+* 2: 512
+* 3: 1024
+* 4: 2048
+* 5: 4096
+* others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu
+* NAME
+* ib_path_rec_mtu
+*
+* DESCRIPTION
+* Get encoded path MTU.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_mtu(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)(p_rec->mtu & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path MTU.
+* 1: 256
+* 2: 512
+* 3: 1024
+* 4: 2048
+* 5: 4096
+* others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu_sel
+* NAME
+* ib_path_rec_mtu_sel
+*
+* DESCRIPTION
+* Get encoded path MTU selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_mtu_sel(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path MTU selector value (for queries).
+* 0: greater than MTU specified
+* 1: less than MTU specified
+* 2: exactly the MTU specified
+* 3: largest MTU available
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate
+* NAME
+* ib_path_rec_rate
+*
+* DESCRIPTION
+* Get encoded path rate.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_rate(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)(p_rec->rate & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path rate.
+* 2: 2.5 Gb/sec.
+* 3: 10 Gb/sec.
+* 4: 30 Gb/sec.
+* others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate_sel
+* NAME
+* ib_path_rec_rate_sel
+*
+* DESCRIPTION
+* Get encoded path rate selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_rate_sel(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path rate selector value (for queries).
+* 0: greater than rate specified
+* 1: less than rate specified
+* 2: exactly the rate specified
+* 3: largest rate available
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life
+* NAME
+* ib_path_rec_pkt_life
+*
+* DESCRIPTION
+* Get encoded path pkt_life.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_pkt_life(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)(p_rec->pkt_life & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path pkt_life = 4.096 µsec * 2 PacketLifeTime.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life_sel
+* NAME
+* ib_path_rec_pkt_life_sel
+*
+* DESCRIPTION
+* Get encoded path pkt_lifetime selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_pkt_life_sel(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6 ));
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Encoded path pkt_lifetime selector value (for queries).
+* 0: greater than rate specified
+* 1: less than rate specified
+* 2: exactly the rate specified
+* 3: smallest packet lifetime available
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_flow_lbl
+* NAME
+* ib_path_rec_flow_lbl
+*
+* DESCRIPTION
+* Get flow label.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint32_t AL_API
+ib_path_rec_flow_lbl(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( ((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Flow label of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_hop_limit
+* NAME
+* ib_path_rec_hop_limit
+*
+* DESCRIPTION
+* Get hop limit.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_rec_hop_limit(
+ IN const ib_path_rec_t* const p_rec )
+{
+ return( (uint8_t)(p_rec->hop_flow_raw & 0x000000FF ) );
+}
+/*
+* PARAMETERS
+* p_rec
+* [in] Pointer to the path record object.
+*
+* RETURN VALUES
+* Hop limit of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_path_rec_t
+*********/
+
+/****s* IBA Base: Constants/IB_CLASS_CAP_TRAP
+* NAME
+* IB_CLASS_CAP_TRAP
+*
+* DESCRIPTION
+* ClassPortInfo CapabilityMask bits. This bit will be set
+* if the class supports Trap() MADs (13.4.8.1).
+*
+* SEE ALSO
+* ib_class_port_info_t, IB_CLASS_CAP_GETSET
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_TRAP 0x0001
+/*********/
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET
+* NAME
+* IB_CLASS_CAP_GETSET
+*
+* DESCRIPTION
+* ClassPortInfo CapabilityMask bits. This bit will be set
+* if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1).
+*
+* SEE ALSO
+* ib_class_port_info_t, IB_CLASS_CAP_TRAP
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_GETSET 0x0002
+/*********/
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET
+* NAME
+* IB_CLASS_CAP_GETSET
+*
+* DESCRIPTION
+* Mask bits to extract the reponse time value from the
+* resp_time_val field of ib_class_port_info_t.
+*
+* SEE ALSO
+* ib_class_port_info_t
+*
+* SOURCE
+*/
+#define IB_CLASS_RESP_TIME_MASK 0x1F
+/*********/
+/****s* IBA Base: Types/ib_class_port_info_t
+* NAME
+* ib_class_port_info_t
+*
+* DESCRIPTION
+* IBA defined ClassPortInfo attribute (13.4.8.1)
+* route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_class_port_info
+{
+ uint8_t base_ver;
+ uint8_t class_ver;
+ ib_net16_t cap_mask;
+ ib_net32_t resp_time_val;
+ ib_gid_t redir_gid;
+ ib_net32_t redir_tc_sl_fl;
+ ib_net16_t redir_lid;
+ ib_net16_t redir_pkey;
+ ib_net32_t redir_qp;
+ ib_net32_t redir_qkey;
+ ib_gid_t trap_gid;
+ ib_net32_t trap_tc_sl_fl;
+ ib_net16_t trap_lid;
+ ib_net16_t trap_pkey;
+ ib_net32_t trap_hop_qp;
+ ib_net32_t trap_qkey;
+
+} PACK_SUFFIX ib_class_port_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* base_ver
+* Maximum supported MAD Base Version.
+*
+* class_ver
+* Maximum supported management class version.
+*
+* cap_mask
+* Supported capabilities of this management class.
+*
+* resp_time_value
+* Maximum expected response time.
+*
+* redr_gid
+* GID to use for redirection, or zero
+*
+* recdir_tc_sl_fl
+* Traffic class, service level and flow label the requester
+* should use if the service is redirected.
+*
+* redir_lid
+* LID used for redirection, or zero
+*
+* redir_pkey
+* P_Key used for redirection
+*
+* redir_qp
+* QP number used for redirection
+*
+* redir_qkey
+* Q_Key associated with the redirected QP. This shall be the
+* well known Q_Key value.
+*
+* trap_gid
+* GID value used for trap messages from this service.
+*
+* trap_tc_sl_fl
+* Traffic class, service level and flow label used for
+* trap messages originated by this service.
+*
+* trap_lid
+* LID used for trap messages, or zero
+*
+* trap_pkey
+* P_Key used for trap messages
+*
+* trap_hop_qp
+* Hop limit (upper 8 bits) and QP number used for trap messages
+*
+* trap_qkey
+* Q_Key associated with the trap messages QP.
+*
+* SEE ALSO
+* IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP
+*
+*********/
+/****s* IBA Base: Types/ib_sm_info_t
+* NAME
+* ib_sm_info_t
+*
+* DESCRIPTION
+* SMInfo structure (14.2.5.13).
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_sm_info
+{
+ ib_net64_t guid;
+ ib_net64_t sm_key;
+ ib_net32_t act_count;
+ uint8_t pri_state;
+
+} PACK_SUFFIX ib_sm_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* guid
+* Port GUID for this SM.
+*
+* sm_key
+* SM_Key of this SM.
+*
+* act_count
+* Activity counter used as a heartbeat.
+*
+* pri_state
+* Priority and State information
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_priority
+* NAME
+* ib_sminfo_get_priority
+*
+* DESCRIPTION
+* Returns the priority value.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_sminfo_get_priority(
+ IN const ib_sm_info_t* const p_smi )
+{
+ return( (uint8_t)((p_smi->pri_state & 0xF0)>>4) );
+}
+/*
+* PARAMETERS
+* p_smi
+* [in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+* Returns the priority value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_state
+* NAME
+* ib_sminfo_get_state
+*
+* DESCRIPTION
+* Returns the state value.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_sminfo_get_state(
+ IN const ib_sm_info_t* const p_smi )
+{
+ return( (uint8_t)(p_smi->pri_state & 0x0F) );
+}
+/*
+* PARAMETERS
+* p_smi
+* [in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+* Returns the state value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_mad_t
+* NAME
+* ib_mad_t
+*
+* DESCRIPTION
+* IBA defined MAD header (13.4.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_mad
+{
+ uint8_t base_ver;
+ uint8_t mgmt_class;
+ uint8_t class_ver;
+ uint8_t method;
+ ib_net16_t status;
+ ib_net16_t class_spec;
+ ib_net64_t trans_id;
+ ib_net16_t attr_id;
+ ib_net16_t resv;
+ ib_net32_t attr_mod;
+} PACK_SUFFIX ib_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* base_ver
+* MAD base format.
+*
+* mgmt_class
+* Class of operation.
+*
+* class_ver
+* Version of MAD class-specific format.
+*
+* method
+* Method to perform, including 'R' bit.
+*
+* status
+* Status of operation.
+*
+* class_spec
+* Reserved for subnet management.
+*
+* trans_id
+* Transaction ID.
+*
+* attr_id
+* Attribute ID.
+*
+* resv
+* Reserved field.
+*
+* attr_mod
+* Attribute modifier.
+*
+* SEE ALSO
+*********/
+
+
+/****s* IBA Base: Types/ib_rmpp_mad_t
+* NAME
+* ib_rmpp_mad_t
+*
+* DESCRIPTION
+* IBA defined MAD RMPP header (13.6.2.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_rmpp_mad
+{
+ ib_mad_t common_hdr;
+
+ uint8_t rmpp_version;
+ uint8_t rmpp_type;
+ uint8_t rmpp_flags;
+ uint8_t rmpp_status;
+
+ ib_net32_t seg_num;
+ ib_net32_t paylen_newwin;
+
+} PACK_SUFFIX ib_rmpp_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+
+/****f* IBA Base: Types/ib_mad_init_new
+* NAME
+* ib_mad_init_new
+*
+* DESCRIPTION
+* Initializes a MAD common header.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_mad_init_new(
+ IN ib_mad_t* const p_mad,
+ IN const uint8_t mgmt_class,
+ IN const uint8_t class_ver,
+ IN const uint8_t method,
+ IN const ib_net64_t trans_id,
+ IN const ib_net16_t attr_id,
+ IN const ib_net32_t attr_mod )
+{
+ CL_ASSERT( p_mad );
+ p_mad->base_ver = 1;
+ p_mad->mgmt_class = mgmt_class;
+ p_mad->class_ver = class_ver;
+ p_mad->method = method;
+ p_mad->status = 0;
+ p_mad->class_spec = 0;
+ p_mad->trans_id = trans_id;
+ p_mad->attr_id = attr_id;
+ p_mad->resv = 0;
+ p_mad->attr_mod = attr_mod;
+}
+/*
+* PARAMETERS
+* p_mad
+* [in] Pointer to the MAD common header.
+*
+* mgmt_class
+* [in] Class of operation.
+*
+* class_ver
+* [in] Version of MAD class-specific format.
+*
+* method
+* [in] Method to perform, including 'R' bit.
+*
+* trans_Id
+* [in] Transaction ID.
+*
+* attr_id
+* [in] Attribute ID.
+*
+* attr_mod
+* [in] Attribute modifier.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_init_response
+* NAME
+* ib_mad_init_response
+*
+* DESCRIPTION
+* Initializes a MAD common header as a response.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_mad_init_response(
+ IN const ib_mad_t* const p_req_mad,
+ IN ib_mad_t* const p_mad,
+ IN const ib_net16_t status )
+{
+ CL_ASSERT( p_req_mad );
+ CL_ASSERT( p_mad );
+ *p_mad = *p_req_mad;
+ p_mad->status = status;
+ if( p_mad->method == IB_MAD_METHOD_SET )
+ p_mad->method = IB_MAD_METHOD_GET;
+ p_mad->method |= IB_MAD_METHOD_RESP_MASK;
+}
+/*
+* PARAMETERS
+* p_req_mad
+* [in] Pointer to the MAD common header in the original request MAD.
+*
+* p_mad
+* [in] Pointer to the MAD common header to initialize.
+*
+* status
+* [in] MAD Status value to return;
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* p_req_mad and p_mad may point to the same MAD.
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_is_response
+* NAME
+* ib_mad_is_response
+*
+* DESCRIPTION
+* Returns TRUE if the MAD is a response ('R' bit set),
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_mad_is_response(
+ IN const ib_mad_t* const p_mad )
+{
+ CL_ASSERT( p_mad );
+ return( (p_mad->method & IB_MAD_METHOD_RESP_MASK) ==
+ IB_MAD_METHOD_RESP_MASK );
+}
+/*
+* PARAMETERS
+* p_mad
+* [in] Pointer to the MAD.
+*
+* RETURN VALUES
+* Returns TRUE if the MAD is a response ('R' bit set),
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+
+#define IB_RMPP_TYPE_DATA 1
+#define IB_RMPP_TYPE_ACK 2
+#define IB_RMPP_TYPE_STOP 3
+#define IB_RMPP_TYPE_ABORT 4
+
+#define IB_RMPP_NO_RESP_TIME 0x1F
+#define IB_RMPP_FLAG_ACTIVE 0x01
+#define IB_RMPP_FLAG_FIRST 0x02
+#define IB_RMPP_FLAG_LAST 0x04
+
+#define IB_RMPP_STATUS_SUCCESS 0
+#define IB_RMPP_STATUS_RESX 1 /* resources exhausted */
+#define IB_RMPP_STATUS_T2L 118 /* time too long */
+#define IB_RMPP_STATUS_BAD_LEN 119 /* incon. last and payload len */
+#define IB_RMPP_STATUS_BAD_SEG 120 /* incon. first and segment no */
+#define IB_RMPP_STATUS_BADT 121 /* bad rmpp type */
+#define IB_RMPP_STATUS_W2S 122 /* newwindowlast too small */
+#define IB_RMPP_STATUS_S2B 123 /* segment no too big */
+#define IB_RMPP_STATUS_BAD_STATUS 124 /* illegal status */
+#define IB_RMPP_STATUS_UNV 125 /* unsupported version */
+#define IB_RMPP_STATUS_TMR 126 /* too many retries */
+#define IB_RMPP_STATUS_UNSPEC 127 /* unspecified */
+
+
+/****f* IBA Base: Types/ib_rmpp_is_flag_set
+* NAME
+* ib_rmpp_is_flag_set
+*
+* DESCRIPTION
+* Returns TRUE if the MAD has the given RMPP flag set.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_rmpp_is_flag_set(
+ IN const ib_rmpp_mad_t* const p_rmpp_mad,
+ IN const uint8_t flag )
+{
+ CL_ASSERT( p_rmpp_mad );
+ return( (p_rmpp_mad->rmpp_flags & flag) == flag );
+}
+/*
+* PARAMETERS
+* ib_rmpp_mad_t
+* [in] Pointer to a MAD with an RMPP header.
+*
+* flag
+* [in] The RMPP flag being examined.
+*
+* RETURN VALUES
+* Returns TRUE if the MAD has the given RMPP flag set.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_mad_t, ib_rmpp_mad_t
+*********/
+
+AL_INLINE void AL_API
+ib_rmpp_set_resp_time(
+ IN ib_rmpp_mad_t* const p_rmpp_mad,
+ IN const uint8_t resp_time )
+{
+ CL_ASSERT( p_rmpp_mad );
+ p_rmpp_mad->rmpp_flags |= (resp_time << 3);
+}
+
+
+AL_INLINE uint8_t AL_API
+ib_rmpp_get_resp_time(
+ IN const ib_rmpp_mad_t* const p_rmpp_mad )
+{
+ CL_ASSERT( p_rmpp_mad );
+ return( (uint8_t)(p_rmpp_mad->rmpp_flags >> 3) );
+}
+
+
+/****d* IBA Base: Constants/IB_SMP_DIRECTION
+* NAME
+* IB_SMP_DIRECTION
+*
+* DESCRIPTION
+* The Direction bit for directed route SMPs.
+*
+* SOURCE
+*/
+#define IB_SMP_DIRECTION_HO 0x8000
+#define IB_SMP_DIRECTION (CL_HTON16(IB_SMP_DIRECTION_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMP_STATUS_MASK
+* NAME
+* IB_SMP_STATUS_MASK
+*
+* DESCRIPTION
+* Mask value for extracting status from a directed route SMP.
+*
+* SOURCE
+*/
+#define IB_SMP_STATUS_MASK_HO 0x7FFF
+#define IB_SMP_STATUS_MASK (CL_HTON16(IB_SMP_STATUS_MASK_HO))
+/**********/
+
+/****s* IBA Base: Types/ib_smp_t
+* NAME
+* ib_smp_t
+*
+* DESCRIPTION
+* IBA defined SMP. (14.2.1.2)
+*
+* SYNOPSIS
+*/
+#define IB_SMP_DATA_SIZE 64
+#include <complib/cl_packon.h>
+typedef struct _ib_smp
+{
+ uint8_t base_ver;
+ uint8_t mgmt_class;
+ uint8_t class_ver;
+ uint8_t method;
+ ib_net16_t status;
+ uint8_t hop_ptr;
+ uint8_t hop_count;
+ ib_net64_t trans_id;
+ ib_net16_t attr_id;
+ ib_net16_t resv;
+ ib_net32_t attr_mod;
+ ib_net64_t m_key;
+ ib_net16_t dr_slid;
+ ib_net16_t dr_dlid;
+ uint32_t resv1[7];
+ uint8_t data[IB_SMP_DATA_SIZE];
+ uint8_t initial_path[IB_SUBNET_PATH_HOPS_MAX];
+ uint8_t return_path[IB_SUBNET_PATH_HOPS_MAX];
+
+} PACK_SUFFIX ib_smp_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* base_ver
+* MAD base format.
+*
+* mgmt_class
+* Class of operation.
+*
+* class_ver
+* Version of MAD class-specific format.
+*
+* method
+* Method to perform, including 'R' bit.
+*
+* status
+* Status of operation.
+*
+* hop_ptr
+* Hop pointer for directed route MADs.
+*
+* hop_count
+* Hop count for directed route MADs.
+*
+* trans_Id
+* Transaction ID.
+*
+* attr_id
+* Attribute ID.
+*
+* resv
+* Reserved field.
+*
+* attr_mod
+* Attribute modifier.
+*
+* m_key
+* Management key value.
+*
+* dr_slid
+* Directed route source LID.
+*
+* dr_dlid
+* Directed route destination LID.
+*
+* resv0
+* Reserved for 64 byte alignment.
+*
+* data
+* MAD data payload.
+*
+* initial_path
+* Outbound port list.
+*
+* return_path
+* Inbound port list.
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_smp_get_status
+* NAME
+* ib_smp_get_status
+*
+* DESCRIPTION
+* Returns the SMP status value in network order.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net16_t AL_API
+ib_smp_get_status(
+ IN const ib_smp_t* const p_smp )
+{
+ return( (ib_net16_t)(p_smp->status & IB_SMP_STATUS_MASK) );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+* Returns the SMP status value in network order.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_is_response
+* NAME
+* ib_smp_is_response
+*
+* DESCRIPTION
+* Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_smp_is_response(
+ IN const ib_smp_t* const p_smp )
+{
+ return( ib_mad_is_response( (const ib_mad_t*)p_smp ) );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+* Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_smp_t
+*********/
+/****f* IBA Base: Types/ib_smp_is_d
+* NAME
+* ib_smp_is_d
+*
+* DESCRIPTION
+* Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_smp_is_d(
+ IN const ib_smp_t* const p_smp )
+{
+ return( (p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+* Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_init_new
+* NAME
+* ib_smp_init_new
+*
+* DESCRIPTION
+* Initializes a MAD common header.
+*
+* TODO
+* This is too big for inlining, but leave it here for now
+* since there is not yet another convient spot.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_smp_init_new(
+ IN ib_smp_t* const p_smp,
+ IN const uint8_t method,
+ IN const ib_net64_t trans_id,
+ IN const ib_net16_t attr_id,
+ IN const ib_net32_t attr_mod,
+ IN const uint8_t hop_count,
+ IN const ib_net64_t m_key,
+ IN const uint8_t* path_out,
+ IN const ib_net16_t dr_slid,
+ IN const ib_net16_t dr_dlid )
+{
+ CL_ASSERT( p_smp );
+ CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );
+ p_smp->base_ver = 1;
+ p_smp->mgmt_class = IB_MCLASS_SUBN_DIR;
+ p_smp->class_ver = 1;
+ p_smp->method = method;
+ p_smp->status = 0;
+ p_smp->hop_ptr = 0;
+ p_smp->hop_count = hop_count;
+ p_smp->trans_id = trans_id;
+ p_smp->attr_id = attr_id;
+ p_smp->resv = 0;
+ p_smp->attr_mod = attr_mod;
+ p_smp->m_key = m_key;
+ p_smp->dr_slid = dr_slid;
+ p_smp->dr_dlid = dr_dlid;
+
+ cl_memclr( p_smp->resv1,
+ sizeof(p_smp->resv1) +
+ sizeof(p_smp->data) +
+ sizeof(p_smp->initial_path) +
+ sizeof(p_smp->return_path) );
+
+ /* copy the path */
+ cl_memcpy( &p_smp->initial_path, path_out,
+ sizeof( p_smp->initial_path ) );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SMP packet.
+*
+* method
+* [in] Method to perform, including 'R' bit.
+*
+* trans_Id
+* [in] Transaction ID.
+*
+* attr_id
+* [in] Attribute ID.
+*
+* attr_mod
+* [in] Attribute modifier.
+*
+* hop_count
+* [in] Number of hops in the path.
+*
+* m_key
+* [in] Management key for this SMP.
+*
+* path_out
+* [in] Port array for outbound path.
+*
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Payload area is initialized to zero.
+*
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+/****f* IBA Base: Types/ib_smp_get_payload_ptr
+* NAME
+* ib_smp_get_payload_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SMP payload area.
+*
+* SYNOPSIS
+*/
+AL_INLINE void* AL_API
+ib_smp_get_payload_ptr(
+ IN const ib_smp_t* const p_smp )
+{
+ return( (void*)p_smp->data );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+* Pointer to SMP payload area.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_node_info_t
+* NAME
+* ib_node_info_t
+*
+* DESCRIPTION
+* IBA defined NodeInfo. (14.2.5.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_node_info
+{
+ uint8_t base_version;
+ uint8_t class_version;
+ uint8_t node_type;
+ uint8_t num_ports;
+ ib_net64_t sys_guid;
+ ib_net64_t node_guid;
+ ib_net64_t port_guid;
+ ib_net16_t partition_cap;
+ ib_net16_t device_id;
+ ib_net32_t revision;
+ ib_net32_t port_num_vendor_id;
+
+} PACK_SUFFIX ib_node_info_t;
+#include <complib/cl_packoff.h>
+/************/
+/****s* IBA Base: Types/ib_sa_mad_t
+* NAME
+* ib_sa_mad_t
+*
+* DESCRIPTION
+* IBA defined SA MAD format. (15.2.1)
+*
+* SYNOPSIS
+*/
+#define IB_SA_DATA_SIZE 200
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sa_mad
+{
+ uint8_t base_ver;
+ uint8_t mgmt_class;
+ uint8_t class_ver;
+ uint8_t method;
+ ib_net16_t status;
+ ib_net16_t resv;
+ ib_net64_t trans_id;
+ ib_net16_t attr_id;
+ ib_net16_t resv1;
+ ib_net32_t attr_mod;
+
+ uint8_t rmpp_version;
+ uint8_t rmpp_type;
+ uint8_t rmpp_flags;
+ uint8_t rmpp_status;
+
+ ib_net32_t seg_num;
+ ib_net32_t paylen_newwin;
+
+ ib_net64_t sm_key;
+
+ ib_net16_t attr_offset;
+ ib_net16_t resv3;
+
+ ib_net64_t comp_mask;
+
+ uint8_t data[IB_SA_DATA_SIZE];
+} PACK_SUFFIX ib_sa_mad_t;
+#include <complib/cl_packoff.h>
+/**********/
+#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE)
+
+
+
+AL_INLINE uint32_t AL_API
+ib_get_attr_size(
+ IN const ib_net16_t attr_offset )
+{
+ return( ((uint32_t)cl_ntoh16( attr_offset )) << 3 );
+}
+
+AL_INLINE ib_net16_t AL_API
+ib_get_attr_offset(
+ IN const uint32_t attr_size )
+{
+ return( cl_hton16( (uint16_t)(attr_size >> 3) ) );
+}
+
+
+/****f* IBA Base: Types/ib_sa_mad_get_payload_ptr
+* NAME
+* ib_sa_mad_get_payload_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SA MAD's payload area.
+*
+* SYNOPSIS
+*/
+AL_INLINE void* AL_API
+ib_sa_mad_get_payload_ptr(
+ IN const ib_sa_mad_t* const p_sa_mad )
+{
+ return( (void*)p_sa_mad->data );
+}
+/*
+* PARAMETERS
+* p_smp
+* [in] Pointer to the SA MAD packet.
+*
+* RETURN VALUES
+* Pointer to SA MAD payload area.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+#define IB_NODE_INFO_PORT_NUM_MASK (CL_NTOH32(0xFF000000))
+#define IB_NODE_INFO_VEND_ID_MASK (CL_NTOH32(0x00FFFFFF))
+#if CPU_LE
+ #define IB_NODE_INFO_PORT_NUM_SHIFT 0
+#else
+ #define IB_NODE_INFO_PORT_NUM_SHIFT 24
+#endif
+
+/****f* IBA Base: Types/ib_node_info_get_local_port_num
+* NAME
+* ib_node_info_get_local_port_num
+*
+* DESCRIPTION
+* Gets a the local port number from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_node_info_get_local_port_num(
+ IN const ib_node_info_t* const p_ni )
+{
+ return( (uint8_t)(( p_ni->port_num_vendor_id &
+ IB_NODE_INFO_PORT_NUM_MASK )
+ >> IB_NODE_INFO_PORT_NUM_SHIFT ));
+}
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+* Local port number that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_node_info_t
+*********/
+/****f* IBA Base: Types/ib_node_info_get_vendor_id
+* NAME
+* ib_node_info_get_vendor_id
+*
+* DESCRIPTION
+* Gets the VendorID from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t AL_API
+ib_node_info_get_vendor_id(
+ IN const ib_node_info_t* const p_ni )
+{
+ return( (ib_net32_t)( p_ni->port_num_vendor_id &
+ IB_NODE_INFO_VEND_ID_MASK ) );
+}
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+* VendorID that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_node_info_t
+*********/
+
+#define IB_NODE_DESCRIPTION_SIZE 64
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_desc
+{
+ // Node String is an array of UTF-8 character that
+ // describes the node in text format
+ // Note that this string is NOT NULL TERMINATED!
+ uint8_t description[IB_NODE_DESCRIPTION_SIZE];
+
+} PACK_SUFFIX ib_node_desc_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_record_t
+{
+ ib_net16_t lid;
+ ib_net16_t resv;
+ ib_node_info_t node_info;
+ ib_node_desc_t node_desc;
+ uint8_t pad[4];
+
+} PACK_SUFFIX ib_node_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_port_info_t
+* NAME
+* ib_port_info_t
+*
+* DESCRIPTION
+* IBA defined PortInfo. (14.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_info
+{
+ ib_net64_t m_key;
+ ib_net64_t subnet_prefix;
+ ib_net16_t base_lid;
+ ib_net16_t master_sm_base_lid;
+ ib_net32_t capability_mask;
+ ib_net16_t diag_code;
+ ib_net16_t m_key_lease_period;
+ uint8_t local_port_num;
+ uint8_t link_width_enabled;
+ uint8_t link_width_supported;
+ uint8_t link_width_active;
+ uint8_t state_info1; /* LinkSpeedSupported and PortState */
+ uint8_t state_info2; /* PortPhysState and LinkDownDefaultState */
+ uint8_t mkey_lmc;
+ uint8_t link_speed; /* LinkSpeedEnabled and LinkSpeedActive */
+ uint8_t mtu_smsl;
+ uint8_t vl_cap; /* VLCap and InitType */
+ uint8_t vl_high_limit;
+ uint8_t vl_arb_high_cap;
+ uint8_t vl_arb_low_cap;
+ uint8_t mtu_cap;
+ uint8_t vl_stall_life;
+ uint8_t vl_enforce;
+ ib_net16_t m_key_violations;
+ ib_net16_t p_key_violations;
+ ib_net16_t q_key_violations;
+ uint8_t guid_cap;
+ uint8_t subnet_timeout; /* cli_rereg(1b), resrv(
+2b), timeout(5b) */
+ uint8_t resp_time_value;
+ uint8_t error_threshold;
+
+} PACK_SUFFIX ib_port_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_PORT_STATE_MASK 0x0F
+#define IB_PORT_LMC_MASK 0x07
+#define IB_PORT_MPB_MASK 0xC0
+#define IB_PORT_MPB_SHIFT 6
+#define IB_PORT_LINK_SPEED_SHIFT 4
+#define IB_PORT_LINK_SPEED_SUPPORTED_MASK 0xF0
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK 0xF0
+#define IB_PORT_LINK_SPEED_ENABLED_MASK 0x0F
+#define IB_PORT_PHYS_STATE_MASK 0xF0
+#define IB_PORT_PHYS_STATE_SHIFT 4
+#define IB_PORT_LNKDWNDFTSTATE_MASK 0x0F
+
+#define IB_PORT_CAP_RESV0 (CL_NTOH32(0x00000001))
+#define IB_PORT_CAP_IS_SM (CL_NTOH32(0x00000002))
+#define IB_PORT_CAP_HAS_NOTICE (CL_NTOH32(0x00000004))
+#define IB_PORT_CAP_HAS_TRAP (CL_NTOH32(0x00000008))
+#define IB_PORT_CAP_HAS_IPD (CL_NTOH32(0x00000010))
+#define IB_PORT_CAP_HAS_AUTO_MIG (CL_NTOH32(0x00000020))
+#define IB_PORT_CAP_HAS_SL_MAP (CL_NTOH32(0x00000040))
+#define IB_PORT_CAP_HAS_NV_MKEY (CL_NTOH32(0x00000080))
+#define IB_PORT_CAP_HAS_NV_PKEY (CL_NTOH32(0x00000100))
+#define IB_PORT_CAP_HAS_LED_INFO (CL_NTOH32(0x00000200))
+#define IB_PORT_CAP_SM_DISAB (CL_NTOH32(0x00000400))
+#define IB_PORT_CAP_HAS_SYS_IMG_GUID (CL_NTOH32(0x00000800))
+#define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_NTOH32(0x00001000))
+#define IB_PORT_CAP_RESV13 (CL_NTOH32(0x00002000))
+#define IB_PORT_CAP_RESV14 (CL_NTOH32(0x00004000))
+#define IB_PORT_CAP_RESV15 (CL_NTOH32(0x00008000))
+#define IB_PORT_CAP_HAS_COM_MGT (CL_NTOH32(0x00010000))
+#define IB_PORT_CAP_HAS_SNMP (CL_NTOH32(0x00020000))
+#define IB_PORT_CAP_REINIT (CL_NTOH32(0x00040000))
+#define IB_PORT_CAP_HAS_DEV_MGT (CL_NTOH32(0x00080000))
+#define IB_PORT_CAP_HAS_VEND_CLS (CL_NTOH32(0x00100000))
+#define IB_PORT_CAP_HAS_DR_NTC (CL_NTOH32(0x00200000))
+#define IB_PORT_CAP_HAS_CAP_NTC (CL_NTOH32(0x00400000))
+#define IB_PORT_CAP_HAS_BM (CL_NTOH32(0x00800000))
+#define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_NTOH32(0x01000000))
+#define IB_PORT_CAP_HAS_CLIENT_REREG (CL_NTOH32(0x02000000))
+#define IB_PORT_CAP_RESV26 (CL_NTOH32(0x04000000))
+#define IB_PORT_CAP_RESV27 (CL_NTOH32(0x08000000))
+#define IB_PORT_CAP_RESV28 (CL_NTOH32(0x10000000))
+#define IB_PORT_CAP_RESV29 (CL_NTOH32(0x20000000))
+#define IB_PORT_CAP_RESV30 (CL_NTOH32(0x40000000))
+#define IB_PORT_CAP_RESV31 (CL_NTOH32(0x80000000))
+
+/****f* IBA Base: Types/ib_port_info_get_port_state
+* NAME
+* ib_port_info_get_port_state
+*
+* DESCRIPTION
+* Returns the port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_port_state(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->state_info1 & IB_PORT_STATE_MASK) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_port_state
+* NAME
+* ib_port_info_set_port_state
+*
+* DESCRIPTION
+* Sets the port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_port_state(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t port_state )
+{
+ p_pi->state_info1 = (uint8_t)((p_pi->state_info1 & 0xF0) | port_state );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* port_state
+* [in] Port state value to set.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_vl_cap
+* NAME
+* ib_port_info_get_vl_cap
+*
+* DESCRIPTION
+* Gets the VL Capability of a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_vl_cap(
+ IN const ib_port_info_t* const p_pi)
+{
+ return((p_pi->vl_cap >> 4) & 0x0F);
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* VL_CAP field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_op_vls
+* NAME
+* ib_port_info_get_op_vls
+*
+* DESCRIPTION
+* Gets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_op_vls(
+ IN const ib_port_info_t* const p_pi)
+{
+ return((p_pi->vl_enforce >> 4) & 0x0F);
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* OP_VLS field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_op_vls
+* NAME
+* ib_port_info_set_op_vls
+*
+* DESCRIPTION
+* Sets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_op_vls(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t op_vls )
+{
+ p_pi->vl_enforce = (uint8_t)((p_pi->vl_enforce & 0x0F) | (op_vls << 4) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* op_vls
+* [in] Encoded operation VLs value.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_state_no_change
+* NAME
+* ib_port_info_set_state_no_change
+*
+* DESCRIPTION
+* Sets the port state fields to the value for "no change".
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_state_no_change(
+ IN ib_port_info_t* const p_pi )
+{
+ ib_port_info_set_port_state( p_pi, 0 );
+ p_pi->state_info2 = 0;
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_sup
+* NAME
+* ib_port_info_get_link_speed_sup
+*
+* DESCRIPTION
+* Returns the encoded value for the link speed supported.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_link_speed_sup(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)((p_pi->state_info1 &
+ IB_PORT_LINK_SPEED_SUPPORTED_MASK) >>
+ IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_speed_sup
+* NAME
+* ib_port_info_set_link_speed_sup
+*
+* DESCRIPTION
+* Given an integer of the supported link speed supported.
+* Set the appropriate bits in state_info1
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_link_speed_sup(
+ IN uint8_t const speed,
+ IN ib_port_info_t* p_pi )
+{
+ p_pi->state_info1 =
+ ( ~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1 ) |
+ ( IB_PORT_LINK_SPEED_SUPPORTED_MASK &
+ (speed << IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+* speed
+* [in] Supported Speeds Code.
+*
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_port_phys_state
+* NAME
+* ib_port_info_get_port_phys_state
+*
+* DESCRIPTION
+* Returns the encoded value for the port physical state.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_port_phys_state(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)((p_pi->state_info2 &
+ IB_PORT_PHYS_STATE_MASK) >>
+ IB_PORT_PHYS_STATE_SHIFT) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the encoded value for the port physical state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_port_phys_state.
+* NAME
+* ib_port_info_set_port_phys_state
+*
+* DESCRIPTION
+* Given an integer of the port physical state,
+* Set the appropriate bits in state_info2
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_port_phys_state(
+ IN uint8_t const phys_state,
+ IN ib_port_info_t* p_pi )
+{
+ p_pi->state_info2 =
+ ( ~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2 ) |
+ ( IB_PORT_PHYS_STATE_MASK &
+ (phys_state << IB_PORT_PHYS_STATE_SHIFT) );
+}
+/*
+* PARAMETERS
+* phys_state
+* [in] port physical state.
+*
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_down_def_state
+* NAME
+* ib_port_info_get_link_down_def_state
+*
+* DESCRIPTION
+* Returns the link down default state.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_link_down_def_state(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* link down default state of the port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_down_def_state
+* NAME
+* ib_port_info_set_link_down_def_state
+*
+* DESCRIPTION
+* Sets the link down default state of the port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_link_down_def_state(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t link_dwn_state )
+{
+ p_pi->state_info2 = (uint8_t)((p_pi->state_info2 & 0xF0) | link_dwn_state );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* link_dwn_state
+* [in] Link down default state of the port.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active
+* NAME
+* ib_port_info_get_link_speed_active
+*
+* DESCRIPTION
+* Returns the Link Speed Active value assigned to this port.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_link_speed_active(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)((p_pi->link_speed &
+ IB_PORT_LINK_SPEED_ACTIVE_MASK) >>
+ IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the link speed active value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+#define IB_LINK_WIDTH_ACTIVE_1X 1
+#define IB_LINK_WIDTH_ACTIVE_4X 2
+#define IB_LINK_WIDTH_ACTIVE_12X 8
+#define IB_LINK_SPEED_ACTIVE_2_5 1
+#define IB_LINK_SPEED_ACTIVE_5 2
+#define IB_LINK_SPEED_ACTIVE_10 4
+
+/* following v1 ver1.2 p901 */
+#define IB_MAX_RATE 10
+#define IB_PATH_RECORD_RATE_2_5_GBS 2
+#define IB_PATH_RECORD_RATE_10_GBS 3
+#define IB_PATH_RECORD_RATE_30_GBS 4
+#define IB_PATH_RECORD_RATE_5_GBS 5
+#define IB_PATH_RECORD_RATE_20_GBS 6
+#define IB_PATH_RECORD_RATE_40_GBS 7
+#define IB_PATH_RECORD_RATE_60_GBS 8
+#define IB_PATH_RECORD_RATE_80_GBS 9
+#define IB_PATH_RECORD_RATE_120_GBS 10
+
+/****f* IBA Base: Types/ib_port_info_compute_rate
+* NAME
+* ib_port_info_compute_rate
+*
+* DESCRIPTION
+* Returns the encoded value for the path rate.
+*
+* SYNOPSIS
+*/
+
+AL_INLINE uint8_t AL_API
+ib_port_info_compute_rate(
+ IN const ib_port_info_t* const p_pi )
+{
+ switch (ib_port_info_get_link_speed_active(p_pi))
+ {
+ case IB_LINK_SPEED_ACTIVE_2_5:
+ switch(p_pi->link_width_active)
+ {
+ case IB_LINK_WIDTH_ACTIVE_1X:
+ return IB_PATH_RECORD_RATE_2_5_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_4X:
+ return IB_PATH_RECORD_RATE_10_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_12X:
+ return IB_PATH_RECORD_RATE_30_GBS;
+
+ default:
+ return IB_PATH_RECORD_RATE_2_5_GBS;
+ }
+ break;
+ case IB_LINK_SPEED_ACTIVE_5:
+ switch (p_pi->link_width_active)
+ {
+ case IB_LINK_WIDTH_ACTIVE_1X:
+ return IB_PATH_RECORD_RATE_5_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_4X:
+ return IB_PATH_RECORD_RATE_20_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_12X:
+ return IB_PATH_RECORD_RATE_60_GBS;
+
+ default:
+ return IB_PATH_RECORD_RATE_5_GBS;
+ }
+ break;
+ case IB_LINK_SPEED_ACTIVE_10:
+ switch (p_pi->link_width_active)
+ {
+ case IB_LINK_WIDTH_ACTIVE_1X:
+ return IB_PATH_RECORD_RATE_10_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_4X:
+ return IB_PATH_RECORD_RATE_40_GBS;
+
+ case IB_LINK_WIDTH_ACTIVE_12X:
+ return IB_PATH_RECORD_RATE_120_GBS;
+
+ default:
+ return IB_PATH_RECORD_RATE_10_GBS;
+ }
+ break;
+ default:
+ return IB_PATH_RECORD_RATE_2_5_GBS;
+ }
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_path_get_ipd
+* NAME
+* ib_path_get_ipd
+*
+* DESCRIPTION
+* Returns the encoded value for the inter packet delay.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_path_get_ipd(
+ IN uint8_t local_link_width_supported,
+ IN uint8_t path_rec_rate )
+{
+ uint8_t ipd = 0;
+
+ switch(local_link_width_supported)
+ {
+ //link_width_supported = 1: 1x
+ case 1:
+ break;
+
+ //link_width_supported = 3: 1x or 4x
+ case 3:
+ switch(path_rec_rate & 0x3F)
+ {
+ case IB_PATH_RECORD_RATE_2_5_GBS:
+ ipd = 3;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ //link_width_supported = 11: 1x or 4x or 12x
+ case 11:
+ switch(path_rec_rate & 0x3F)
+ {
+ case IB_PATH_RECORD_RATE_2_5_GBS:
+ ipd = 11;
+ break;
+ case IB_PATH_RECORD_RATE_10_GBS:
+ ipd = 2;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ipd;
+}
+/*
+* PARAMETERS
+* local_link_width_supported
+* [in] link with supported for this port
+*
+* path_rec_rate
+* [in] rate field of the path record
+*
+* RETURN VALUES
+* Returns the ipd
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* IBA Base: Types/ib_port_info_get_mtu_cap
+* NAME
+* ib_port_info_get_mtu_cap
+*
+* DESCRIPTION
+* Returns the encoded value for the maximum MTU supported by this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_mtu_cap(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->mtu_cap & 0x0F) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_neighbor_mtu
+* NAME
+* ib_port_info_get_neighbor_mtu
+*
+* DESCRIPTION
+* Returns the encoded value for the neighbor MTU at this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_neighbor_mtu(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)((p_pi->mtu_smsl & 0xF0) >> 4) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the encoded value for the neighbor MTU at this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_neighbor_mtu
+* NAME
+* ib_port_info_set_neighbor_mtu
+*
+* DESCRIPTION
+* Sets the Neighbor MTU value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_neighbor_mtu(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t mtu )
+{
+ CL_ASSERT( mtu <= 5 );
+ CL_ASSERT( mtu != 0 );
+ p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0x0F) | (mtu << 4));
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* mtu
+* [in] Encoded MTU value to set
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_timeout
+* NAME
+* ib_port_info_set_timeout
+*
+* DESCRIPTION
+* Sets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_timeout(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t timeout )
+{
+ CL_ASSERT( timeout <= 0x1F );
+ p_pi->subnet_timeout =
+ (uint8_t)(
+ (p_pi->subnet_timeout & 0x80) | (timeout & 0x1F));
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* timeout
+* [in] Encoded timeout value to set
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_client_rereg
+* NAME
+* ib_port_info_set_client_rereg
+*
+* DESCRIPTION
+* Sets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_port_info_set_client_rereg(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t client_rereg )
+{
+ CL_ASSERT( client_rereg <= 0x1 );
+ p_pi->subnet_timeout =
+ (uint8_t)(
+ (p_pi->subnet_timeout & 0x1F) | ((client_rereg << 7) & 0x80));
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* client_rereg
+* [in] Client reregistration value to set either 1 or 0
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_timeout
+* NAME
+* ib_port_info_get_timeout
+*
+* DESCRIPTION
+* Gets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_timeout(
+ IN ib_port_info_t const* p_pi )
+{
+ return(p_pi->subnet_timeout & 0x1F );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* The encoded timeout value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_client_rereg
+* NAME
+* ib_port_info_get_client_rereg
+*
+* DESCRIPTION
+* Gets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_client_rereg(
+ IN ib_port_info_t const* p_pi )
+{
+ return ( (p_pi->subnet_timeout & 0x80 ) >> 7);
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* client_rereg
+* [in] Client reregistration value to get either 1 or 0
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_hoq_lifetime
+* NAME
+* ib_port_info_set_hoq_lifetime
+*
+* DESCRIPTION
+* Sets the Head of Queue Lifetime for which a packet can live in the head
+* of VL queue
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_port_info_set_hoq_lifetime(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t hoq_life )
+{
+ p_pi->vl_stall_life = (uint8_t)((hoq_life & 0x1f) |
+ (p_pi->vl_stall_life & 0xe0));
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* hoq_life
+* [in] Encoded lifetime value to set
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_hoq_lifetime
+* NAME
+* ib_port_info_get_hoq_lifetime
+*
+* DESCRIPTION
+* Gets the Head of Queue Lifetime for which a packet can live in the head
+* of VL queue
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_hoq_lifetime(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->vl_stall_life & 0x1f) );
+}
+
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Encoded lifetime value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_vl_stall_count
+* NAME
+* ib_port_info_set_vl_stall_count
+*
+* DESCRIPTION
+* Sets the VL Stall Count which define the number of contigious
+* HLL (hoq) drops that will put the VL into stalled mode.
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_port_info_set_vl_stall_count(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t vl_stall_count )
+{
+ p_pi->vl_stall_life = (uint8_t)((p_pi->vl_stall_life & 0x1f) |
+ ((vl_stall_count << 5) & 0xe0));
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* vl_stall_count
+* [in] value to set
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_vl_stall_count
+ * NAME
+ * ib_port_info_get_vl_stall_count
+ *
+ * DESCRIPTION
+ * Gets the VL Stall Count which define the number of contigious
+ * HLL (hoq) drops that will put the VL into stalled mode
+ *
+ * SYNOPSIS
+ */
+AL_INLINE uint8_t AL_API
+ib_port_info_get_vl_stall_count(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->vl_stall_life & 0xe0) >> 5);
+}
+
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* vl stall count
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_lmc
+* NAME
+* ib_port_info_get_lmc
+*
+* DESCRIPTION
+* Returns the LMC value assigned to this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_lmc(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->mkey_lmc & IB_PORT_LMC_MASK) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_lmc
+* NAME
+* ib_port_info_set_lmc
+*
+* DESCRIPTION
+* Sets the LMC value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_lmc(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t lmc )
+{
+ CL_ASSERT( lmc <= 0x7 );
+ p_pi->mkey_lmc = (uint8_t)((p_pi->mkey_lmc & 0xF8) | lmc);
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* lmc
+* [in] LMC value to set, must be less than 7.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_enabled
+* NAME
+* ib_port_info_get_link_speed_enabled
+*
+* DESCRIPTION
+* Returns the link speed enabled value assigned to this port.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_port_info_get_link_speed_enabled(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)(p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_link_speed_enabled
+* NAME
+* ib_port_info_set_link_speed_enabled
+*
+* DESCRIPTION
+* Sets the link speed enabled value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_link_speed_enabled(
+ IN ib_port_info_t* const p_pi,
+ IN const uint8_t link_speed_enabled )
+{
+ p_pi->link_speed = (uint8_t)((p_pi->link_speed & 0xF0) | link_speed_enabled );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* link_speed_enabled
+* [in] link speed enabled value to set.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_mpb
+* NAME
+* ib_port_info_get_mpb
+*
+* DESCRIPTION
+* Returns the M_Key protect bits assigned to this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_port_info_get_mpb(
+ IN const ib_port_info_t* const p_pi )
+{
+ return( (uint8_t)((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >>
+ IB_PORT_MPB_SHIFT) );
+}
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the M_Key protect bits assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_mpb
+* NAME
+* ib_port_info_set_mpb
+*
+* DESCRIPTION
+* Set the M_Key protect bits of this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_port_info_set_mpb(
+ IN ib_port_info_t* p_pi,
+ IN uint8_t mpb )
+{
+ p_pi->mkey_lmc =
+ (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) |
+ ( IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT) );
+}
+/*
+* PARAMETERS
+* mpb
+* [in] M_Key protect bits
+* p_ni
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd
+* NAME
+* ib_port_info_set_phy_and_overrun_err_thd
+*
+* DESCRIPTION
+* Sets the Phy Link and Credits Overrun Errors Threshold
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_port_info_set_phy_and_overrun_err_thd(
+ IN ib_port_info_t* const p_pi,
+ IN uint8_t phy_threshold,
+ IN uint8_t overrun_threshold )
+{
+ p_pi->error_threshold =
+ (uint8_t)( ((phy_threshold & 0x0F) << 4) | (overrun_threshold & 0x0F) );
+}
+/*
+* PARAMETERS
+* p_pi
+* [in] Pointer to a PortInfo attribute.
+*
+* phy_threshold
+* [in] Physical Link Errors Threshold above which Trap 129 is generated
+*
+* overrun_threshold
+* [in] Credits overrun Errors Threshold above which Trap 129 is generated
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+typedef uint8_t ib_svc_name_t[64];
+
+#include <complib/cl_packon.h>
+typedef struct _ib_service_record
+{
+ ib_net64_t service_id;
+ ib_gid_t service_gid;
+ ib_net16_t service_pkey;
+ ib_net16_t resv;
+ ib_net32_t service_lease;
+ uint8_t service_key[16];
+ ib_svc_name_t service_name;
+ uint8_t service_data8[16];
+ ib_net16_t service_data16[8];
+ ib_net32_t service_data32[4];
+ ib_net64_t service_data64[2];
+
+} PACK_SUFFIX ib_service_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_portinfo_record
+{
+ ib_net16_t lid;
+ uint8_t port_num;
+ uint8_t resv;
+ ib_port_info_t port_info;
+ uint8_t pad[6];
+
+} PACK_SUFFIX ib_portinfo_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_link_record
+{
+ ib_net16_t from_lid;
+ uint8_t from_port_num;
+ uint8_t to_port_num;
+ ib_net16_t to_lid;
+ uint8_t pad[2];
+
+} PACK_SUFFIX ib_link_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sminfo_record
+{
+ ib_net16_t lid;
+ uint16_t resv0;
+ ib_sm_info_t sm_info;
+ uint8_t pad[7];
+
+} PACK_SUFFIX ib_sminfo_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_lft_record_t
+* NAME
+* ib_lft_record_t
+*
+* DESCRIPTION
+* IBA defined LinearForwardingTable. (14.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_lft_record
+{
+ ib_net16_t lid;
+ ib_net16_t block_num;
+ uint32_t resv0;
+ uint8_t lft[64];
+} PACK_SUFFIX ib_lft_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_switch_info_t
+* NAME
+* ib_switch_info_t
+*
+* DESCRIPTION
+* IBA defined SwitchInfo. (14.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info
+{
+ ib_net16_t lin_cap;
+ ib_net16_t rand_cap;
+ ib_net16_t mcast_cap;
+ ib_net16_t lin_top;
+ uint8_t def_port;
+ uint8_t def_mcast_pri_port;
+ uint8_t def_mcast_not_port;
+ uint8_t life_state;
+ ib_net16_t lids_per_port;
+ ib_net16_t enforce_cap;
+ uint8_t flags;
+
+} PACK_SUFFIX ib_switch_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info_record
+{
+ ib_net16_t lid;
+ uint16_t resv0;
+ ib_switch_info_t switch_info;
+ uint8_t pad[3];
+
+} PACK_SUFFIX ib_switch_info_record_t;
+#include <complib/cl_packoff.h>
+
+#define IB_SWITCH_PSC 0x04
+
+/****f* IBA Base: Types/ib_switch_info_get_state_change
+* NAME
+* ib_switch_info_get_state_change
+*
+* DESCRIPTION
+* Returns the value of the state change flag.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t AL_API
+ib_switch_info_get_state_change(
+ IN const ib_switch_info_t* const p_si )
+{
+ return( (p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC );
+}
+/*
+* PARAMETERS
+* p_si
+* [in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+* Returns the value of the state change flag.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_switch_info_clear_state_change
+* NAME
+* ib_switch_info_clear_state_change
+*
+* DESCRIPTION
+* Clears the switch's state change bit.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_switch_info_clear_state_change(
+ IN ib_switch_info_t* const p_si )
+{
+ p_si->life_state = (uint8_t)(p_si->life_state & 0xFB);
+}
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+* Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* IBA Base: Types/ib_switch_info_is_enhanced_port_0
+* NAME
+* ib_switch_info_is_enhanced_port_0
+*
+* DESCRIPTION
+* Returns TRUE if the enhancedPort0 bit is on (meaning the switch
+* port zero supports enhanced functions).
+* Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t AL_API
+ib_switch_info_is_enhanced_port_0(
+ IN const ib_switch_info_t* const p_si )
+{
+ return( (p_si->flags & 0x08) == 0x08 );
+}
+/*
+* PARAMETERS
+* p_si
+* [in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+* Returns TRUE if the switch supports enhanced port 0. FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_guid_info_t
+* NAME
+* ib_guid_info_t
+*
+* DESCRIPTION
+* IBA defined GuidInfo. (14.2.5.5)
+*
+* SYNOPSIS
+*/
+#define GUID_TABLE_MAX_ENTRIES 8
+
+#include <complib/cl_packon.h>
+typedef struct _ib_guid_info
+{
+ ib_net64_t guid[GUID_TABLE_MAX_ENTRIES];
+
+} PACK_SUFFIX ib_guid_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_NUM_PKEY_ELEMENTS_IN_BLOCK 32
+/****s* IBA Base: Types/ib_pkey_table_t
+* NAME
+* ib_pkey_table_t
+*
+* DESCRIPTION
+* IBA defined PKey table. (14.2.5.7)
+*
+* SYNOPSIS
+*/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table
+{
+ ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK];
+
+} PACK_SUFFIX ib_pkey_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_pkey_table_record_t
+* NAME
+* ib_pkey_table_record_t
+*
+* DESCRIPTION
+* IBA defined P_Key Table Record for SA Query. (15.2.5.11)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table_record
+{
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0
+ uint16_t block_num;
+ uint8_t port_num; // for swithc: port number, for CA: reserved
+ uint8_t reserved1;
+ uint16_t reserved2;
+ ib_pkey_table_t pkey_tbl;
+
+} PACK_SUFFIX ib_pkey_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_MAX_NUM_VLS 16
+/****s* IBA Base: Types/ib_slvl_table_t
+* NAME
+* ib_slvl_table_t
+*
+* DESCRIPTION
+* IBA defined SL2VL Mapping Table Attribute. (14.2.5.8)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table
+{
+ uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2];
+} PACK_SUFFIX ib_slvl_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_slvl_table_record_t
+* NAME
+* ib_slvl_table_record_t
+*
+* DESCRIPTION
+* IBA defined Sl to VL Mapping Table Record for SA Query. (15.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table_record
+{
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0
+ uint8_t in_port_num; // reserved for CA's
+ uint8_t out_port_num; // reserved for CA's
+ uint32_t resv;
+ ib_slvl_table_t slvl_tbl;
+
+} PACK_SUFFIX ib_slvl_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****f* IBA Base: Types/ib_slvl_table_set
+* NAME
+* ib_slvl_table_set
+*
+* DESCRIPTION
+* Set slvl table entry.
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_slvl_table_set(
+ IN ib_slvl_table_t* p_slvl_tbl,
+ IN uint8_t sl_index,
+ IN uint8_t vl )
+{
+ uint8_t idx = sl_index/2;
+ CL_ASSERT(vl <= 15);
+ CL_ASSERT(sl_index <= 15);
+
+ if (sl_index%2)
+ {
+ /* this is an odd sl. Need to update the ls bits */
+ p_slvl_tbl->raw_vl_by_sl[idx] = ( p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0 ) | vl ;
+ }
+ else
+ {
+ /* this is an even sl. Need to update the ms bits */
+ p_slvl_tbl->raw_vl_by_sl[idx] = ( vl << 4 ) | ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );
+ }
+}
+/*
+* PARAMETERS
+* p_slvl_tbl
+* [in] pointer to ib_slvl_table_t object.
+*
+* sl_index
+* [in] the sl index in the table to be updated.
+*
+* vl
+* [in] the vl value to update for that sl.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+* ib_slvl_table_t
+*********/
+
+/****f* IBA Base: Types/ib_slvl_table_get
+* NAME
+* ib_slvl_table_get
+*
+* DESCRIPTION
+* Get slvl table entry.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t AL_API
+ib_slvl_table_get(
+ IN const ib_slvl_table_t* p_slvl_tbl,
+ IN uint8_t sl_index )
+{
+ uint8_t idx = sl_index/2;
+ CL_ASSERT(sl_index <= 15);
+
+ if (sl_index%2)
+ {
+ /* this is an odd sl. Need to return the ls bits. */
+ return ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );
+ }
+ else
+ {
+ /* this is an even sl. Need to return the ms bits. */
+ return ( (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4 );
+ }
+}
+/*
+* PARAMETERS
+* p_slvl_tbl
+* [in] pointer to ib_slvl_table_t object.
+*
+* sl_index
+* [in] the sl index in the table whose value should be returned.
+*
+* RETURN VALUES
+* vl that is updated for that sl.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_slvl_table_t
+*********/
+
+/****s* IBA Base: Types/ib_vl_arb_element_t
+* NAME
+* ib_vl_arb_element_t
+*
+* DESCRIPTION
+* IBA defined VL Arbitration Table Element. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_element
+{
+ uint8_t vl;
+ uint8_t weight;
+
+} PACK_SUFFIX ib_vl_arb_element_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
+/****s* IBA Base: Types/ib_vl_arb_table_t
+* NAME
+* ib_vl_arb_table_t
+*
+* DESCRIPTION
+* IBA defined VL Arbitration Table. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table
+{
+ ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
+
+} PACK_SUFFIX ib_vl_arb_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_vl_arb_table_record_t
+* NAME
+* ib_vl_arb_table_record_t
+*
+* DESCRIPTION
+* IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table_record
+{
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0
+ uint8_t port_num;
+ uint8_t block_num;
+ uint32_t reserved;
+ ib_vl_arb_table_t vl_arb_tbl;
+
+} PACK_SUFFIX ib_vl_arb_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/*
+ * Global route header information received with unreliable datagram messages
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_grh
+{
+ ib_net32_t ver_class_flow;
+ ib_net16_t resv1;
+ uint8_t resv2;
+ uint8_t hop_limit;
+ ib_gid_t src_gid;
+ ib_gid_t dest_gid;
+
+} PACK_SUFFIX ib_grh_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_grh_get_ver_class_flow
+* NAME
+* ib_grh_get_ver_class_flow
+*
+* DESCRIPTION
+* Get encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_grh_get_ver_class_flow(
+ IN const ib_net32_t ver_class_flow,
+ OUT uint8_t* const p_ver,
+ OUT uint8_t* const p_tclass,
+ OUT uint32_t* const p_flow_lbl )
+{
+ ib_net32_t tmp_ver_class_flow;
+
+ if (p_ver)
+ *p_ver = (uint8_t)(ver_class_flow & 0x0f);
+
+ tmp_ver_class_flow = ver_class_flow >> 4;
+
+ if (p_tclass)
+ *p_tclass = (uint8_t)(tmp_ver_class_flow & 0xff);
+
+ tmp_ver_class_flow = tmp_ver_class_flow >> 8;
+
+ if (p_flow_lbl)
+ *p_flow_lbl = tmp_ver_class_flow & 0xfffff;
+}
+/*
+* PARAMETERS
+* ver_class_flow
+* [in] the version, traffic class and flow label info.
+*
+* RETURN VALUES
+* p_ver
+* [out] pointer to the version info.
+*
+* p_tclass
+* [out] pointer to the traffic class info.
+*
+* p_flow_lbl
+* [out] pointer to the flow label info
+*
+* NOTES
+*
+* SEE ALSO
+* ib_grh_t
+*********/
+
+/****f* IBA Base: Types/ib_grh_set_ver_class_flow
+* NAME
+* ib_grh_set_ver_class_flow
+*
+* DESCRIPTION
+* Set encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t AL_API
+ib_grh_set_ver_class_flow(
+ IN const uint8_t ver,
+ IN const uint8_t tclass,
+ IN const uint32_t flow_lbl )
+{
+ ib_net32_t ver_class_flow;
+
+ ver_class_flow = flow_lbl;
+ ver_class_flow = ver_class_flow << 8;
+ ver_class_flow = ver_class_flow | tclass;
+ ver_class_flow = ver_class_flow << 4;
+ ver_class_flow = ver_class_flow | ver;
+ return (ver_class_flow);
+}
+/*
+* PARAMETERS
+* ver
+* [in] the version info.
+*
+* tclass
+* [in] the traffic class info.
+*
+* flow_lbl
+* [in] the flow label info
+*
+* RETURN VALUES
+* ver_class_flow
+* [out] the version, traffic class and flow label info.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_grh_t
+*********/
+
+/****s* IBA Base: Types/ib_member_rec_t
+* NAME
+* ib_member_rec_t
+*
+* DESCRIPTION
+* Multicast member record, used to create, join, and leave multicast
+* groups.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_member_rec
+{
+ ib_gid_t mgid;
+ ib_gid_t port_gid;
+ ib_net32_t qkey;
+ ib_net16_t mlid;
+ uint8_t mtu;
+ uint8_t tclass;
+ ib_net16_t pkey;
+ uint8_t rate;
+ uint8_t pkt_life;
+ ib_net32_t sl_flow_hop;
+ uint8_t scope_state;
+/* uint8_t proxy_join:1; */
+/* TODO : Under DDK got C4214 which note that using bitfield can cause problems
+ in porting to other compilers */
+ uint8_t proxy_join;
+ uint8_t reserved[2];
+ uint8_t pad[4];
+
+} PACK_SUFFIX ib_member_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* mgid
+* Multicast GID address for this multicast group.
+*
+* port_gid
+* Valid GID of the endpoint joining this multicast group.
+*
+* requestor_gid
+* GID of the endpoint making this request on hehave of port_gid.
+*
+* qkey
+* Q_Key to be sued by this multicast group.
+*
+* mlid
+* Multicast LID for this multicast group.
+*
+* mtu
+* MTU and MTU selector fields to use on this path
+*
+* tclass
+* Another global routing parameter.
+*
+* pkey
+* Partition key (P_Key) to use for this member.
+*
+* rate
+* Rate and rate selector fields to use on this path.
+*
+* pkt_life
+* Packet lifetime
+*
+* sl_flow_hop
+* Global routing parameters: service level, hop count, and flow label.
+*
+* scope_state
+* MGID scope and JoinState of multicast request.
+*
+* proxy_join
+* Enables others in the Partition to proxy add/remove from the group
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_member_get_sl_flow_hop
+* NAME
+* ib_member_get_sl_flow_hop
+*
+* DESCRIPTION
+* Get encoded sl flow label and hop limit
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_member_get_sl_flow_hop(
+ IN const ib_net32_t sl_flow_hop,
+ OUT uint8_t* const p_sl,
+ OUT uint32_t* const p_flow_lbl,
+ OUT uint8_t* const p_hop )
+{
+ ib_net32_t tmp_sl_flow_hop;
+
+ if (p_sl)
+ *p_sl = (uint8_t)(sl_flow_hop & 0x0f);
+
+ tmp_sl_flow_hop = sl_flow_hop >> 4;
+
+ if (p_flow_lbl)
+ *p_flow_lbl = (uint32_t)(tmp_sl_flow_hop & 0xfffff);
+
+ tmp_sl_flow_hop = tmp_sl_flow_hop >> 20;
+
+ if (p_hop)
+ *p_hop = (uint8_t)(tmp_sl_flow_hop & 0xff);
+}
+/*
+* PARAMETERS
+* sl_flow_hop
+* [in] the sl flow label and hop limit of MC Group
+*
+* RETURN VALUES
+* p_sl
+* [out] pointer to the service level
+*
+* p_flow_lbl
+* [out] pointer to the flow label info
+*
+* p_hop
+* [out] pointer to the hop count limit.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_sl_flow_hop
+* NAME
+* ib_member_set_sl_flow_hop
+*
+* DESCRIPTION
+* Set encoded version, sl flow and hop
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t AL_API
+ib_member_set_sl_flow_hop(
+ IN const uint8_t sl,
+ IN const uint32_t flow_label,
+ IN const uint8_t hop_limit )
+{
+ ib_net32_t sl_flow_hop;
+
+ sl_flow_hop = hop_limit;
+ sl_flow_hop = sl_flow_hop << 20;
+ sl_flow_hop = sl_flow_hop | flow_label;
+ sl_flow_hop = sl_flow_hop << 2;
+ sl_flow_hop = sl_flow_hop | sl;
+ return (sl_flow_hop);
+}
+/*
+* PARAMETERS
+* sl
+* [in] the service level.
+*
+* flow_lbl
+* [in] the flow label info
+*
+* hop_limit
+* [in] the hop limit.
+*
+* RETURN VALUES
+* sl_flow_hop
+* [out] the sl flow label and hop limit
+*
+* NOTES
+*
+* SEE ALSO
+* ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_get_scope_state
+* NAME
+* ib_member_get_scope_state
+*
+* DESCRIPTION
+* Get encoded MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_member_get_scope_state(
+ IN const uint8_t scope_state,
+ OUT uint8_t* const p_scope,
+ OUT uint8_t* const p_state )
+{
+ uint8_t tmp_scope_state;
+
+ if (p_state)
+ *p_state = (uint8_t)(scope_state & 0x0f);
+
+ tmp_scope_state = scope_state >> 4;
+
+ if (p_scope)
+ *p_scope = (uint8_t)(tmp_scope_state & 0x0f);
+
+}
+/*
+* PARAMETERS
+* scope_state
+* [in] the scope and state
+*
+* RETURN VALUES
+* p_scope
+* [out] pointer to the MGID scope
+*
+* p_state
+* [out] pointer to the join state
+*
+* NOTES
+*
+* SEE ALSO
+* ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_scope_state
+* NAME
+* ib_member_set_scope_state
+*
+* DESCRIPTION
+* Set encoded version, MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_member_set_scope_state(
+ IN const uint8_t scope,
+ IN const uint8_t state )
+{
+ uint8_t scope_state;
+
+ scope_state = scope;
+ scope_state = scope_state << 4;
+ scope_state = scope_state | state;
+ return (scope_state);
+}
+/*
+* PARAMETERS
+* scope
+* [in] the MGID scope
+*
+* state
+* [in] the JoinState
+*
+* RETURN VALUES
+* scope_state
+* [out] the encoded one
+*
+* NOTES
+*
+* SEE ALSO
+* ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_join_state
+* NAME
+* ib_member_set_join_state
+*
+* DESCRIPTION
+* Set JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_member_set_join_state(
+ IN OUT ib_member_rec_t *p_mc_rec,
+ IN const uint8_t state )
+{
+ /* keep the scope as it is */
+ p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state);
+}
+/*
+* PARAMETERS
+* p_mc_rec
+* [in] pointer to the member record
+*
+* state
+* [in] the JoinState
+*
+* RETURN VALUES
+* NONE
+*
+* NOTES
+*
+* SEE ALSO
+* ib_member_rec_t
+*********/
+
+/*
+ * Join State Codes:
+ */
+#define IB_MC_REC_STATE_FULL_MEMBER 0x01
+#define IB_MC_REC_STATE_NON_MEMBER 0x02
+#define IB_MC_REC_STATE_SEND_ONLY_MEMBER 0x04
+
+/*
+ * Generic MAD notice types
+ */
+#define IB_NOTICE_TYPE_FATAL 0x00
+#define IB_NOTICE_TYPE_URGENT 0x01
+#define IB_NOTICE_TYPE_SECURITY 0x02
+#define IB_NOTICE_TYPE_SUBN_MGMT 0x03
+#define IB_NOTICE_TYPE_INFO 0x04
+#define IB_NOTICE_TYPE_EMPTY 0x7F
+
+
+#include <complib/cl_packon.h>
+typedef struct _ib_mad_notice_attr // Total Size calc Accumulated
+{
+ uint8_t generic_type; // 1 1
+
+ union _notice_g_or_v
+ {
+ struct _notice_generic // 5 6
+ {
+ uint8_t prod_type_msb;
+ ib_net16_t prod_type_lsb;
+ ib_net16_t trap_num;
+ } PACK_SUFFIX generic;
+
+ struct _notice_vend
+ {
+ uint8_t vend_id_msb;
+ ib_net16_t vend_id_lsb;
+ ib_net16_t dev_id;
+ } PACK_SUFFIX vend;
+ } g_or_v;
+
+ ib_net16_t issuer_lid; // 2 8
+ ib_net16_t toggle_count; // 2 10
+
+ union _data_details // 54 64
+ {
+ struct _raw_data
+ {
+ uint8_t details[54];
+ } PACK_SUFFIX raw_data;
+
+ struct _ntc_64_67
+ {
+ uint8_t res[6];
+ ib_gid_t gid; // the Node or Multicast Group that came in/out
+ } PACK_SUFFIX ntc_64_67;
+
+ struct _ntc_128 {
+ ib_net16_t sw_lid; // the sw lid of which link state changed
+ } PACK_SUFFIX ntc_128;
+
+ struct _ntc_129_131 {
+ ib_net16_t pad;
+ ib_net16_t lid; // lid and port number of the violation
+ uint8_t port_num;
+ } PACK_SUFFIX ntc_129_131;
+
+ struct _ntc_144 {
+ ib_net16_t pad1;
+ ib_net16_t lid; // lid where capability mask changed
+ ib_net16_t pad2;
+ ib_net32_t new_cap_mask; // new capability mask
+ } PACK_SUFFIX ntc_144;
+
+ struct _ntc_145 {
+ ib_net16_t pad1;
+ ib_net16_t lid; // lid where sys guid changed
+ ib_net16_t pad2;
+ ib_net64_t new_sys_guid; // new system image guid
+ } PACK_SUFFIX ntc_145;
+
+ struct _ntc_256 { // total: 54
+ ib_net16_t pad1; // 2
+ ib_net16_t lid; // 2
+ ib_net16_t pad2; // 2
+ uint8_t method; // 1
+ uint8_t pad3; // 1
+ ib_net16_t attr_id; // 2
+ ib_net32_t attr_mod; // 4
+ ib_net64_t mkey; // 8
+ uint8_t dr_slid; // 1
+ uint8_t dr_trunc_hop; // 1
+ uint8_t dr_rtn_path[30]; // 30
+ } PACK_SUFFIX ntc_256;
+
+ struct _ntc_257_258 // violation of p/q_key // 49
+ {
+ ib_net16_t pad1; // 2
+ ib_net16_t lid1; // 2
+ ib_net16_t lid2; // 2
+ ib_net32_t key; // 2
+ uint8_t sl; // 1
+ ib_net32_t qp1; // 4
+ ib_net32_t qp2; // 4
+ ib_gid_t gid1; // 16
+ ib_gid_t gid2; // 16
+ } PACK_SUFFIX ntc_257_258;
+
+ struct _ntc_259 // p/q_key violation with sw info 53
+ {
+ ib_net16_t data_valid; // 2
+ ib_net16_t lid1; // 2
+ ib_net16_t lid2; // 2
+ ib_net32_t key; // 4
+ uint8_t sl; // 1
+ ib_net32_t qp1; // 4
+ uint8_t qp2_msb; // 1
+ ib_net16_t qp2_lsb; // 2
+ ib_gid_t gid1; // 16
+ ib_gid_t gid2; // 16
+ ib_net16_t sw_lid; // 2
+ uint8_t port_no; // 1
+ } PACK_SUFFIX ntc_259;
+
+ } data_details;
+
+ ib_gid_t issuer_gid; // 16 80
+
+} PACK_SUFFIX ib_mad_notice_attr_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_notice_is_generic
+* NAME
+* ib_notice_is_generic
+*
+* DESCRIPTION
+* Check if the notice is generic
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t AL_API
+ib_notice_is_generic(
+ IN const ib_mad_notice_attr_t *p_ntc)
+{
+ return (p_ntc->generic_type & 0x80);
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+* TRUE if mad is generic
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_type
+* NAME
+* ib_notice_get_type
+*
+* DESCRIPTION
+* Get the notice type
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_notice_get_type(
+ IN const ib_mad_notice_attr_t *p_ntc)
+{
+ return p_ntc->generic_type & 0x7f;
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+* TRUE if mad is generic
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_prod_type
+* NAME
+* ib_notice_get_prod_type
+*
+* DESCRIPTION
+* Get the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t AL_API
+ib_notice_get_prod_type(
+ IN const ib_mad_notice_attr_t *p_ntc)
+{
+ uint32_t pt;
+ pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) |
+ (p_ntc->g_or_v.generic.prod_type_msb << 16);
+ return cl_hton32(pt);
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+* The producer type
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_prod_type
+* NAME
+* ib_notice_set_prod_type
+*
+* DESCRIPTION
+* Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_notice_set_prod_type(
+ IN ib_mad_notice_attr_t *p_ntc,
+ IN ib_net32_t prod_type_val)
+{
+ uint32_t ptv = cl_ntoh32(prod_type_val);
+ p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16( (uint16_t)(ptv & 0x0000ffff));
+ p_ntc->g_or_v.generic.prod_type_msb = (uint8_t)( (ptv & 0x00ff0000) >> 16);
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* prod_type
+* [in] The producer Type code
+*
+* RETURN VALUES
+* None
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_vend_id
+* NAME
+* ib_notice_get_vend_id
+*
+* DESCRIPTION
+* Get the Vendor Id of Vendor type Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t AL_API
+ib_notice_get_vend_id(
+ IN const ib_mad_notice_attr_t *p_ntc)
+{
+ uint32_t vi;
+ vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) |
+ (p_ntc->g_or_v.vend.vend_id_msb << 16);
+ return cl_hton32(vi);
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+* The Vendor Id of Vendor type Notice
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_vend_id
+* NAME
+* ib_notice_set_vend_id
+*
+* DESCRIPTION
+* Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE void AL_API
+ib_notice_set_vend_id(
+ IN ib_mad_notice_attr_t *p_ntc,
+ IN ib_net32_t vend_id)
+{
+ uint32_t vi = cl_ntoh32(vend_id);
+ p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t)(vi & 0x0000ffff));
+ p_ntc->g_or_v.vend.vend_id_msb = (uint8_t)((vi & 0x00ff0000) >> 16);
+}
+/*
+* PARAMETERS
+* p_ntc
+* [in] Pointer to the notice MAD attribute
+*
+* vend_id
+* [in] The producer Type code
+*
+* RETURN VALUES
+* None
+*
+* SEE ALSO
+* ib_mad_notice_attr_t
+*********/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info
+{
+ ib_gid_t gid;
+ ib_net16_t lid_range_begin;
+ ib_net16_t lid_range_end;
+ ib_net16_t reserved1;
+ uint8_t is_generic;
+ uint8_t subscribe;
+ ib_net16_t trap_type;
+ union _inform_g_or_v
+ {
+ struct _inform_generic
+ {
+ ib_net16_t trap_num;
+ ib_net32_t qpn_resp_time_val;
+ uint8_t reserved2;
+ uint8_t node_type_msb;
+ ib_net16_t node_type_lsb;
+ } PACK_SUFFIX generic;
+
+ struct _inform_vend
+ {
+ ib_net16_t dev_id;
+ ib_net32_t qpn_resp_time_val;
+ uint8_t reserved2;
+ uint8_t vendor_id_msb;
+ ib_net16_t vendor_id_lsb;
+ } PACK_SUFFIX vend;
+
+ } PACK_SUFFIX g_or_v;
+
+} PACK_SUFFIX ib_inform_info_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time
+* NAME
+* ib_inform_info_get_qpn_resp_time
+*
+* DESCRIPTION
+* Get QPN of the inform info
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_inform_info_get_qpn_resp_time(
+ IN const ib_net32_t qpn_resp_time_val,
+ OUT ib_net32_t* const p_qpn,
+ OUT uint8_t* const p_resp_time_val )
+{
+ uint32_t tmp = cl_ntoh32(qpn_resp_time_val);
+
+ if (p_qpn)
+ *p_qpn = cl_hton32((tmp & 0xffffff00) >> 8);
+
+ if (p_resp_time_val)
+ *p_resp_time_val = (uint8_t)(tmp & 0x0000001f);
+}
+/*
+* PARAMETERS
+* qpn_resp_time_val
+* [in] the qpn and resp time val from the mad
+*
+* RETURN VALUES
+* p_qpn
+* [out] pointer to the qpn
+*
+* p_state
+* [out] pointer to the resp time val
+*
+* NOTES
+*
+* SEE ALSO
+* ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_set_qpn
+* NAME
+* ib_inform_info_set_qpn
+*
+* DESCRIPTION
+* Set the QPN of the inform info
+*
+* SYNOPSIS
+*/
+OSM_INLINE void AL_API
+ib_inform_info_set_qpn(
+ IN ib_inform_info_t *p_ii,
+ IN ib_net32_t const qpn)
+{
+ uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val);
+ p_ii->g_or_v.generic.qpn_resp_time_val =
+ cl_hton32(
+ (tmp & 0x000000ff) |
+ ((cl_ntoh32(qpn) << 8) & 0xffffff00)
+ );
+}
+/*
+* PARAMETERS
+*
+* NOTES
+*
+* SEE ALSO
+* ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_node_type
+* NAME
+* ib_inform_info_get_node_type
+*
+* DESCRIPTION
+* Get Node Type of the Inform Info
+*
+* SYNOPSIS
+*/
+OSM_INLINE ib_net32_t AL_API
+ib_inform_info_get_node_type(
+ IN const ib_inform_info_t *p_inf)
+{
+ uint32_t nt;
+ nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |
+ (p_inf->g_or_v.generic.node_type_msb << 16);
+ return cl_hton32(nt);
+}
+/*
+* PARAMETERS
+* p_inf
+* [in] pointer to an inform info
+*
+* RETURN VALUES
+* The node type
+*
+* NOTES
+*
+* SEE ALSO
+* ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_vend_id
+* NAME
+* ib_inform_info_get_vend_id
+*
+* DESCRIPTION
+* Get Node Type of the Inform Info
+*
+* SYNOPSIS
+*/
+OSM_INLINE ib_net32_t AL_API
+ib_inform_info_get_vend_id(
+ IN const ib_inform_info_t *p_inf)
+{
+ uint32_t vi;
+ vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) |
+ (p_inf->g_or_v.vend.vendor_id_msb << 16);
+ return cl_hton32(vi);
+}
+/*
+* PARAMETERS
+* p_inf
+* [in] pointer to an inform info
+*
+* RETURN VALUES
+* The node type
+*
+* NOTES
+*
+* SEE ALSO
+* ib_inform_info_t
+*********/
+
+/****s* IBA Base: Types/ib_inform_info_record_t
+* NAME
+* ib_inform_info_record_t
+*
+* DESCRIPTION
+* IBA defined InformInfo Record. (15.2.5.12)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info_record
+{
+ ib_gid_t subscriber_gid;
+ ib_net16_t subscriber_enum;
+ uint8_t reserved[6];
+ ib_inform_info_t inform_info;
+
+} PACK_SUFFIX ib_inform_info_record_t;
+#include <complib/cl_packoff.h>
+
+/****d* IBA Base: Types/DM_SVC_NAME
+* NAME
+* DM_SVC_NAME
+*
+* DESCRIPTION
+* IBA defined Device Management service name (16.3)
+*
+* SYNOPSIS
+*/
+#define DM_SVC_NAME "DeviceManager.IBTA"
+/*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_dm_mad_t
+* NAME
+* ib_dm_mad_t
+*
+* DESCRIPTION
+* IBA defined Device Management MAD (16.3.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_dm_mad
+{
+ ib_mad_t header;
+ uint8_t resv[40];
+
+#define IB_DM_DATA_SIZE 192
+ uint8_t data[IB_DM_DATA_SIZE];
+
+} PACK_SUFFIX ib_dm_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* header
+* Common MAD header.
+*
+* resv
+* Reserved.
+*
+* data
+* Device Management payload. The structure and content of this field
+* depend upon the method, attr_id, and attr_mod fields in the header.
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_iou_info_t
+* NAME
+* ib_iou_info_t
+*
+* DESCRIPTION
+* IBA defined IO Unit information structure (16.3.3.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_iou_info
+{
+ ib_net16_t change_id;
+ uint8_t max_controllers;
+ uint8_t diag_rom;
+
+#define IB_DM_CTRL_LIST_SIZE 128
+
+ uint8_t controller_list[IB_DM_CTRL_LIST_SIZE];
+#define IOC_NOT_INSTALLED 0x0
+#define IOC_INSTALLED 0x1
+// Reserved values 0x02-0xE
+#define SLOT_DOES_NOT_EXIST 0xF
+
+} PACK_SUFFIX ib_iou_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* change_id
+* Value incremented, with rollover, by any change to the controller_list.
+*
+* max_controllers
+* Number of slots in controller_list.
+*
+* diag_rom
+* A byte containing two fields: DiagDeviceID and OptionROM.
+* These fields may be read using the ib_iou_info_diag_dev_id
+* and ib_iou_info_option_rom functions.
+*
+* controller_list
+* A series of 4-bit nibbles, with each nibble representing a slot
+* in the IO Unit. Individual nibbles may be read using the
+* ioc_at_slot function.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_diag_dev_id
+* NAME
+* ib_iou_info_diag_dev_id
+*
+* DESCRIPTION
+* Returns the DiagDeviceID.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_iou_info_diag_dev_id(
+ IN const ib_iou_info_t* const p_iou_info )
+{
+ return( (uint8_t)(p_iou_info->diag_rom >> 6 & 1) );
+}
+/*
+* PARAMETERS
+* p_iou_info
+* [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+* DiagDeviceID field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_option_rom
+* NAME
+* ib_iou_info_option_rom
+*
+* DESCRIPTION
+* Returns the OptionROM.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ib_iou_info_option_rom(
+ IN const ib_iou_info_t* const p_iou_info )
+{
+ return( (uint8_t)(p_iou_info->diag_rom >> 7) );
+}
+/*
+* PARAMETERS
+* p_iou_info
+* [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+* OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ioc_at_slot
+* NAME
+* ioc_at_slot
+*
+* DESCRIPTION
+* Returns the IOC value at the specified slot.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t AL_API
+ioc_at_slot(
+ IN const ib_iou_info_t* const p_iou_info,
+ IN uint8_t slot )
+{
+ if( slot >= IB_DM_CTRL_LIST_SIZE ) return SLOT_DOES_NOT_EXIST;
+ else return (int8_t)
+ ( (slot%2) ?
+ ((p_iou_info->controller_list[slot/2] & 0xf0) >> 4 ):
+ (p_iou_info->controller_list[slot/2] & 0x0f) );
+}
+/*
+* PARAMETERS
+* p_iou_info
+* [in] Pointer to the IO Unit information structure.
+*
+* slot
+* [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+* OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_iou_info_t
+*********/
+
+/****s* IBA Base: Types/ib_ioc_profile_t
+* NAME
+* ib_ioc_profile_t
+*
+* DESCRIPTION
+* IBA defined IO Controller profile structure (16.3.3.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_profile
+{
+ ib_net64_t ioc_guid;
+
+ ib_net32_t vend_id;
+
+ ib_net32_t dev_id;
+ ib_net16_t dev_ver;
+ ib_net16_t resv2;
+
+ ib_net32_t subsys_vend_id;
+ ib_net32_t subsys_id;
+
+ ib_net16_t io_class;
+ ib_net16_t io_subclass;
+ ib_net16_t protocol;
+ ib_net16_t protocol_ver;
+
+ ib_net32_t resv3;
+ ib_net16_t send_msg_depth;
+ uint8_t resv4;
+ uint8_t rdma_read_depth;
+ ib_net32_t send_msg_size;
+ ib_net32_t rdma_size;
+
+ uint8_t ctrl_ops_cap;
+#define CTRL_OPS_CAP_ST 0x01
+#define CTRL_OPS_CAP_SF 0x02
+#define CTRL_OPS_CAP_RT 0x04
+#define CTRL_OPS_CAP_RF 0x08
+#define CTRL_OPS_CAP_WT 0x10
+#define CTRL_OPS_CAP_WF 0x20
+#define CTRL_OPS_CAP_AT 0x40
+#define CTRL_OPS_CAP_AF 0x80
+
+ uint8_t resv5;
+
+ uint8_t num_svc_entries;
+#define MAX_NUM_SVC_ENTRIES 0xff
+
+ uint8_t resv6[9];
+
+#define CTRL_ID_STRING_LEN 64
+ char id_string[CTRL_ID_STRING_LEN];
+
+} PACK_SUFFIX ib_ioc_profile_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* ioc_guid
+* An EUI-64 GUID used to uniquely identify the IO controller.
+*
+* vend_id
+* IO controller vendor ID, IEEE format.
+*
+* dev_id
+* A number assigned by the vendor to identify the type of controller.
+*
+* dev_ver
+* A number assigned by the vendor to identify the divice version.
+*
+* subsys_vend_id
+* ID of the vendor of the enclosure, if any, in which the IO controller
+* resides in IEEE format; otherwise zero.
+*
+* subsys_id
+* A number identifying the subsystem where the controller resides.
+*
+* io_class
+* 0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand
+* Architecture. 0xffff = Vendor specific.
+*
+* io_subclass
+* 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+* Architecture. 0xffff = Vendor specific. This shall be set to 0xfff
+* if the io_class component is 0xffff.
+*
+* protocol
+* 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+* Architecture. 0xffff = Vendor specific. This shall be set to 0xfff
+* if the io_class component is 0xffff.
+*
+* protocol_ver
+* Protocol specific.
+*
+* send_msg_depth
+* Maximum depth of the send message queue.
+*
+* rdma_read_depth
+* Maximum depth of the per-channel RDMA read queue.
+*
+* send_msg_size
+* Maximum size of send messages.
+*
+* ctrl_ops_cap
+* Supported operation types of this IO controller. A bit set to one
+* for affirmation of supported capability.
+*
+* num_svc_entries
+* Number of entries in the service entries table.
+*
+* id_string
+* UTF-8 encoded string for identifying the controller to an operator.
+*
+* SEE ALSO
+* ib_dm_mad_t
+*********/
+
+
+AL_INLINE uint32_t AL_API
+ib_ioc_profile_get_vend_id(
+ IN const ib_ioc_profile_t* const p_ioc_profile )
+{
+ return( cl_ntoh32(p_ioc_profile->vend_id) >> 8 );
+}
+
+
+AL_INLINE void AL_API
+ib_ioc_profile_set_vend_id(
+ IN ib_ioc_profile_t* const p_ioc_profile,
+ IN const uint32_t vend_id )
+{
+ p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8);
+}
+
+
+/****s* IBA Base: Types/ib_svc_entry_t
+* NAME
+* ib_svc_entry_t
+*
+* DESCRIPTION
+* IBA defined IO Controller service entry structure (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entry
+{
+#define MAX_SVC_ENTRY_NAME_LEN 40
+ char name[MAX_SVC_ENTRY_NAME_LEN];
+
+ ib_net64_t id;
+
+} PACK_SUFFIX ib_svc_entry_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* name
+* UTF-8 encoded, null-terminated name of the service.
+*
+* id
+* An identifier of the associated Service.
+*
+* SEE ALSO
+* ib_svc_entries_t
+*********/
+
+
+/****s* IBA Base: Types/ib_svc_entries_t
+* NAME
+* ib_svc_entries_t
+*
+* DESCRIPTION
+* IBA defined IO Controller service entry array (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entries
+{
+#define SVC_ENTRY_COUNT 4
+ ib_svc_entry_t service_entry[SVC_ENTRY_COUNT];
+
+} PACK_SUFFIX ib_svc_entries_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+* service_entry
+* An array of IO controller service entries.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_svc_entry_t
+*********/
+
+
+AL_INLINE void AL_API
+ib_dm_get_slot_lo_hi(
+ IN const ib_net32_t slot_lo_hi,
+ OUT uint8_t *const p_slot,
+ OUT uint8_t *const p_lo,
+ OUT uint8_t *const p_hi )
+{
+ ib_net32_t tmp_slot_lo_hi = CL_NTOH32( slot_lo_hi );
+
+ if( p_slot )
+ *p_slot = (uint8_t)( ( tmp_slot_lo_hi >> 16 ) & 0x0f );
+
+ if( p_hi )
+ *p_hi = (uint8_t)( ( tmp_slot_lo_hi >> 8 ) & 0xff );
+
+ if( p_lo )
+ *p_lo = (uint8_t)( ( tmp_slot_lo_hi >> 0 ) & 0xff );
+}
+
+
+/*
+ * IBA defined information describing an I/O controller
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_info
+{
+ ib_net64_t module_guid;
+ ib_net64_t iou_guid;
+ ib_ioc_profile_t ioc_profile;
+ ib_net64_t access_key;
+ uint16_t initiators_conf;
+ uint8_t resv[38];
+
+} PACK_SUFFIX ib_ioc_info_t;
+#include <complib/cl_packoff.h>
+
+/*
+ * Defines known Communication management class versions
+ */
+#define IB_MCLASS_CM_VER_2 2
+#define IB_MCLASS_CM_VER_1 1
+
+/*
+ * Defines the size of user available data in communication management MADs
+ */
+#define IB_REQ_PDATA_SIZE_VER2 92
+#define IB_MRA_PDATA_SIZE_VER2 222
+#define IB_REJ_PDATA_SIZE_VER2 148
+#define IB_REP_PDATA_SIZE_VER2 196
+#define IB_RTU_PDATA_SIZE_VER2 224
+#define IB_LAP_PDATA_SIZE_VER2 168
+#define IB_APR_PDATA_SIZE_VER2 148
+#define IB_DREQ_PDATA_SIZE_VER2 220
+#define IB_DREP_PDATA_SIZE_VER2 224
+#define IB_SIDR_REQ_PDATA_SIZE_VER2 216
+#define IB_SIDR_REP_PDATA_SIZE_VER2 136
+
+#define IB_REQ_PDATA_SIZE_VER1 92
+#define IB_MRA_PDATA_SIZE_VER1 222
+#define IB_REJ_PDATA_SIZE_VER1 148
+#define IB_REP_PDATA_SIZE_VER1 204
+#define IB_RTU_PDATA_SIZE_VER1 224
+#define IB_LAP_PDATA_SIZE_VER1 168
+#define IB_APR_PDATA_SIZE_VER1 151
+#define IB_DREQ_PDATA_SIZE_VER1 220
+#define IB_DREP_PDATA_SIZE_VER1 224
+#define IB_SIDR_REQ_PDATA_SIZE_VER1 216
+#define IB_SIDR_REP_PDATA_SIZE_VER1 140
+
+#define IB_ARI_SIZE 72 // redefine
+#define IB_APR_INFO_SIZE 72
+
+
+/****d* Access Layer/ib_rej_status_t
+* NAME
+* ib_rej_status_t
+*
+* DESCRIPTION
+* Rejection reasons.
+*
+* SYNOPSIS
+*/
+typedef ib_net16_t ib_rej_status_t;
+/*
+* SEE ALSO
+* ib_cm_rej, ib_cm_rej_rec_t
+*
+* SOURCE
+ */
+#define IB_REJ_INSUF_QP CL_HTON16(1)
+#define IB_REJ_INSUF_EEC CL_HTON16(2)
+#define IB_REJ_INSUF_RESOURCES CL_HTON16(3)
+#define IB_REJ_TIMEOUT CL_HTON16(4)
+#define IB_REJ_UNSUPPORTED CL_HTON16(5)
+#define IB_REJ_INVALID_COMM_ID CL_HTON16(6)
+#define IB_REJ_INVALID_COMM_INSTANCE CL_HTON16(7)
+#define IB_REJ_INVALID_SID CL_HTON16(8)
+#define IB_REJ_INVALID_XPORT CL_HTON16(9)
+#define IB_REJ_STALE_CONN CL_HTON16(10)
+#define IB_REJ_RDC_NOT_EXIST CL_HTON16(11)
+#define IB_REJ_INVALID_GID CL_HTON16(12)
+#define IB_REJ_INVALID_LID CL_HTON16(13)
+#define IB_REJ_INVALID_SL CL_HTON16(14)
+#define IB_REJ_INVALID_TRAFFIC_CLASS CL_HTON16(15)
+#define IB_REJ_INVALID_HOP_LIMIT CL_HTON16(16)
+#define IB_REJ_INVALID_PKT_RATE CL_HTON16(17)
+#define IB_REJ_INVALID_ALT_GID CL_HTON16(18)
+#define IB_REJ_INVALID_ALT_LID CL_HTON16(19)
+#define IB_REJ_INVALID_ALT_SL CL_HTON16(20)
+#define IB_REJ_INVALID_ALT_TRAFFIC_CLASS CL_HTON16(21)
+#define IB_REJ_INVALID_ALT_HOP_LIMIT CL_HTON16(22)
+#define IB_REJ_INVALID_ALT_PKT_RATE CL_HTON16(23)
+#define IB_REJ_PORT_REDIRECT CL_HTON16(24)
+#define IB_REJ_INVALID_MTU CL_HTON16(26)
+#define IB_REJ_INSUFFICIENT_RESP_RES CL_HTON16(27)
+#define IB_REJ_USER_DEFINED CL_HTON16(28)
+#define IB_REJ_INVALID_RNR_RETRY CL_HTON16(29)
+#define IB_REJ_DUPLICATE_LOCAL_COMM_ID CL_HTON16(30)
+#define IB_REJ_INVALID_CLASS_VER CL_HTON16(31)
+#define IB_REJ_INVALID_FLOW_LBL CL_HTON16(32)
+#define IB_REJ_INVALID_ALT_FLOW_LBL CL_HTON16(33)
+
+#define IB_REJ_SERVICE_HANDOFF CL_HTON16(65535)
+/******/
+
+
+/****d* Access Layer/ib_apr_status_t
+* NAME
+* ib_apr_status_t
+*
+* DESCRIPTION
+* Automatic path migration status information.
+*
+* SYNOPSIS
+*/
+typedef uint8_t ib_apr_status_t;
+/*
+* SEE ALSO
+* ib_cm_apr, ib_cm_apr_rec_t
+*
+* SOURCE
+ */
+#define IB_AP_SUCCESS 0
+#define IB_AP_INVALID_COMM_ID 1
+#define IB_AP_UNSUPPORTED 2
+#define IB_AP_REJECT 3
+#define IB_AP_REDIRECT 4
+#define IB_AP_IS_CURRENT 5
+#define IB_AP_INVALID_QPN_EECN 6
+#define IB_AP_INVALID_LID 7
+#define IB_AP_INVALID_GID 8
+#define IB_AP_INVALID_FLOW_LBL 9
+#define IB_AP_INVALID_TCLASS 10
+#define IB_AP_INVALID_HOP_LIMIT 11
+#define IB_AP_INVALID_PKT_RATE 12
+#define IB_AP_INVALID_SL 13
+/******/
+
+/****d* Access Layer/ib_cm_cap_mask_t
+* NAME
+* ib_cm_cap_mask_t
+*
+* DESCRIPTION
+* Capability mask values in ClassPortInfo.
+*
+* SYNOPSIS
+*/
+#define IB_CM_RELIABLE_CONN_CAPABLE CL_HTON16(9)
+#define IB_CM_RELIABLE_DGRM_CAPABLE CL_HTON16(10)
+#define IB_CM_RDGRM_CAPABLE CL_HTON16(11)
+#define IB_CM_UNRELIABLE_CONN_CAPABLE CL_HTON16(12)
+#define IB_CM_SIDR_CAPABLE CL_HTON16(13)
+/*
+* SEE ALSO
+* ib_cm_rep, ib_class_port_info_t
+*
+* SOURCE
+*
+*******/
+
+
+/*
+ * Service ID resolution status
+ */
+typedef uint16_t ib_sidr_status_t;
+#define IB_SIDR_SUCCESS 0
+#define IB_SIDR_UNSUPPORTED 1
+#define IB_SIDR_REJECT 2
+#define IB_SIDR_NO_QP 3
+#define IB_SIDR_REDIRECT 4
+#define IB_SIDR_UNSUPPORTED_VER 5
+
+
+/*
+ * The following definitions are shared between the Access Layer and VPD
+ */
+
+
+typedef struct _ib_ca* __ptr64 ib_ca_handle_t;
+typedef struct _ib_pd* __ptr64 ib_pd_handle_t;
+typedef struct _ib_rdd* __ptr64 ib_rdd_handle_t;
+typedef struct _ib_mr* __ptr64 ib_mr_handle_t;
+typedef struct _ib_mw* __ptr64 ib_mw_handle_t;
+typedef struct _ib_qp* __ptr64 ib_qp_handle_t;
+typedef struct _ib_eec* __ptr64 ib_eec_handle_t;
+typedef struct _ib_cq* __ptr64 ib_cq_handle_t;
+typedef struct _ib_av* __ptr64 ib_av_handle_t;
+typedef struct _ib_mcast* __ptr64 ib_mcast_handle_t;
+
+/* Currently for windows branch we use the extended version of ib special verbs struct
+ in order to be compliant with Infinicon ib_types , later we'll change it to support
+ OpenSM ib_types.h */
+#ifndef WIN32
+
+/****d* Access Layer/ib_api_status_t
+* NAME
+* ib_api_status_t
+*
+* DESCRIPTION
+* Function return codes indicating the success or failure of an API call.
+* Note that success is indicated by the return value IB_SUCCESS, which
+* is always zero.
+*
+* NOTES
+* IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call
+* in the pre-ioctl step itself.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_api_status_t
+{
+ IB_SUCCESS,
+ IB_INSUFFICIENT_RESOURCES,
+ IB_INSUFFICIENT_MEMORY,
+ IB_INVALID_PARAMETER,
+ IB_INVALID_SETTING,
+ IB_NOT_FOUND,
+ IB_TIMEOUT,
+ IB_CANCELED,
+ IB_INTERRUPTED,
+ IB_INVALID_PERMISSION,
+ IB_UNSUPPORTED,
+ IB_OVERFLOW,
+ IB_MAX_MCAST_QPS_REACHED,
+ IB_INVALID_QP_STATE,
+ IB_INVALID_EEC_STATE,
+ IB_INVALID_APM_STATE,
+ IB_INVALID_PORT_STATE,
+ IB_INVALID_STATE,
+ IB_RESOURCE_BUSY,
+ IB_INVALID_PKEY,
+ IB_INVALID_LKEY,
+ IB_INVALID_RKEY,
+ IB_INVALID_MAX_WRS,
+ IB_INVALID_MAX_SGE,
+ IB_INVALID_CQ_SIZE,
+ IB_INVALID_SERVICE_TYPE,
+ IB_INVALID_GID,
+ IB_INVALID_LID,
+ IB_INVALID_GUID,
+ IB_INVALID_CA_HANDLE,
+ IB_INVALID_AV_HANDLE,
+ IB_INVALID_CQ_HANDLE,
+ IB_INVALID_EEC_HANDLE,
+ IB_INVALID_QP_HANDLE,
+ IB_INVALID_PD_HANDLE,
+ IB_INVALID_MR_HANDLE,
+ IB_INVALID_MW_HANDLE,
+ IB_INVALID_RDD_HANDLE,
+ IB_INVALID_MCAST_HANDLE,
+ IB_INVALID_CALLBACK,
+ IB_INVALID_AL_HANDLE, /* InfiniBand Access Layer */
+ IB_INVALID_HANDLE, /* InfiniBand Access Layer */
+ IB_ERROR, /* InfiniBand Access Layer */
+ IB_REMOTE_ERROR, /* Infiniband Access Layer */
+ IB_VERBS_PROCESSING_DONE, /* See Notes above */
+ IB_INVALID_WR_TYPE,
+ IB_QP_IN_TIMEWAIT,
+ IB_EE_IN_TIMEWAIT,
+ IB_INVALID_PORT,
+ IB_NOT_DONE,
+ IB_UNKNOWN_ERROR /* ALWAYS LAST ENUM VALUE! */
+
+} ib_api_status_t;
+/*****/
+
+AL_EXPORT const char* ib_error_str[];
+
+/****f* IBA Base: Types/ib_get_err_str
+* NAME
+* ib_get_err_str
+*
+* DESCRIPTION
+* Returns a string for the specified status value.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char* AL_API
+ib_get_err_str(
+ IN ib_api_status_t status )
+{
+ if( status > IB_UNKNOWN_ERROR )
+ status = IB_UNKNOWN_ERROR;
+ return( ib_error_str[status] );
+}
+/*
+* PARAMETERS
+* status
+* [in] status value
+*
+* RETURN VALUES
+* Pointer to the status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Verbs/ib_async_event_t
+* NAME
+* ib_async_event_t -- Async event types
+*
+* DESCRIPTION
+* This type indicates the reason the async callback was called.
+* The context in the ib_event_rec_t indicates the resource context
+* that associated with the callback. For example, for IB_AE_CQ_ERROR
+* the context provided during the ib_create_cq is returned in the event.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_async_event_t
+{
+ IB_AE_SQ_ERROR = 1,
+ IB_AE_SQ_DRAINED,
+ IB_AE_RQ_ERROR,
+ IB_AE_CQ_ERROR,
+ IB_AE_QP_FATAL,
+ IB_AE_QP_COMM,
+ IB_AE_QP_APM,
+ IB_AE_EEC_FATAL,
+ IB_AE_EEC_COMM,
+ IB_AE_EEC_APM,
+ IB_AE_LOCAL_FATAL,
+ IB_AE_PKEY_TRAP,
+ IB_AE_QKEY_TRAP,
+ IB_AE_MKEY_TRAP,
+ IB_AE_PORT_TRAP,
+ IB_AE_SYSIMG_GUID_TRAP,
+ IB_AE_BUF_OVERRUN,
+ IB_AE_LINK_INTEGRITY,
+ IB_AE_FLOW_CTRL_ERROR,
+ IB_AE_BKEY_TRAP,
+ IB_AE_QP_APM_ERROR,
+ IB_AE_EEC_APM_ERROR,
+ IB_AE_WQ_REQ_ERROR,
+ IB_AE_WQ_ACCESS_ERROR,
+ IB_AE_PORT_ACTIVE,
+ IB_AE_PORT_DOWN,
+ IB_AE_UNKNOWN /* ALWAYS LAST ENUM VALUE */
+
+} ib_async_event_t;
+/*
+* VALUES
+* IB_AE_SQ_ERROR
+* An error occurred when accessing the send queue of the QP or EEC.
+* This event is optional.
+*
+* IB_AE_SQ_DRAINED
+* The send queue of the specified QP has completed the outstanding
+* messages in progress when the state change was requested and, if
+* applicable, has received all acknowledgements for those messages.
+*
+* IB_AE_RQ_ERROR
+* An error occurred when accessing the receive queue of the QP or EEC.
+* This event is optional.
+*
+* IB_AE_CQ_ERROR
+* An error occurred when writing an entry to the CQ.
+*
+* IB_AE_QP_FATAL
+* A catastrophic error occurred while accessing or processing the
+* work queue that prevents reporting of completions.
+*
+* IB_AE_QP_COMM
+* The first packet has arrived for the receive work queue where the
+* QP is still in the RTR state.
+*
+* IB_AE_QP_APM
+* If alternate path migration is supported, this event indicates that
+* the QP connection has migrated to the alternate path.
+*
+* IB_AE_EEC_FATAL
+* If reliable datagram service is supported, this event indicates that
+* a catastrophic error occurred while accessing or processing the EEC
+* that prevents reporting of completions.
+*
+* IB_AE_EEC_COMM
+* If reliable datagram service is supported, this event indicates that
+* the first packet has arrived for the receive work queue where the
+* EEC is still in the RTR state.
+*
+* IB_AE_EEC_APM
+* If reliable datagram service and alternate path migration is supported,
+* this event indicates that the EEC connection has migrated to the
+* alternate path.
+*
+* IB_AE_LOCAL_FATAL
+* A catastrophic HCA error occurred which cannot be attributed to any
+* resource; behavior is indeterminate.
+*
+* IB_AE_PKEY_TRAP
+* A PKEY violation was detected. This event is optional.
+*
+* IB_AE_QKEY_TRAP
+* A QKEY violation was detected. This event is optional.
+*
+* IB_AE_MKEY_TRAP
+* An MKEY violation was detected. This event is optional.
+*
+* IB_AE_PORT_TRAP
+* A port capability change was detected. This event is optional.
+*
+* IB_AE_SYSIMG_GUID_TRAP
+* If the system image GUID is supported, this event indicates that the
+* system image GUID of this HCA has been changed. This event is
+* optional.
+*
+* IB_AE_BUF_OVERRUN
+* The number of consecutive flow control update periods with at least
+* one overrun error in each period has exceeded the threshold specified
+* in the port info attributes. This event is optional.
+*
+* IB_AE_LINK_INTEGRITY
+* The detection of excessively frequent local physical errors has
+* exceeded the threshold specified in the port info attributes. This
+* event is optional.
+*
+* IB_AE_FLOW_CTRL_ERROR
+* An HCA watchdog timer monitoring the arrival of flow control updates
+* has expired without receiving an update. This event is optional.
+*
+* IB_AE_BKEY_TRAP
+* An BKEY violation was detected. This event is optional.
+*
+* IB_AE_QP_APM_ERROR
+* If alternate path migration is supported, this event indicates that
+* an incoming path migration request to this QP was not accepted.
+*
+* IB_AE_EEC_APM_ERROR
+* If reliable datagram service and alternate path migration is supported,
+* this event indicates that an incoming path migration request to this
+* EEC was not accepted.
+*
+* IB_AE_WQ_REQ_ERROR
+* An OpCode violation was detected at the responder.
+*
+* IB_AE_WQ_ACCESS_ERROR
+* An access violation was detected at the responder.
+*
+* IB_AE_PORT_ACTIVE
+* If the port active event is supported, this event is generated
+* when the link becomes active: IB_LINK_ACTIVE.
+*
+* IB_AE_PORT_DOWN
+* The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,
+* IB_LINK_DOWN.
+*
+* IB_AE_UNKNOWN
+* An unknown error occurred which cannot be attributed to any
+* resource; behavior is indeterminate.
+*
+*****/
+
+AL_EXPORT const char* ib_async_event_str[];
+
+/****f* IBA Base: Types/ib_get_async_event_str
+* NAME
+* ib_get_async_event_str
+*
+* DESCRIPTION
+* Returns a string for the specified asynchronous event.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char* AL_API
+ib_get_async_event_str(
+ IN ib_async_event_t event )
+{
+ if( event > IB_AE_UNKNOWN )
+ event = IB_AE_UNKNOWN;
+ return( ib_async_event_str[event] );
+}
+/*
+* PARAMETERS
+* event
+* [in] event value
+*
+* RETURN VALUES
+* Pointer to the asynchronous event description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****s* Verbs/ib_event_rec_t
+* NAME
+* ib_event_rec_t -- Async event notification record
+*
+* DESCRIPTION
+* When an async event callback is made, this structure is passed to indicate
+* the type of event, the source of event that caused it, and the context
+* associated with this event.
+*
+* context -- Context of the resource that caused the event.
+* -- ca_context if this is a port/adapter event.
+* -- qp_context if the source is a QP event
+* -- cq_context if the source is a CQ event.
+* -- ee_context if the source is an EE event.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_event_rec
+{
+ void *context;
+ ib_async_event_t type;
+
+ /* HCA vendor specific event information. */
+ uint64_t vendor_specific;
+
+ /* The following structures are valid only for trap types. */
+ union _trap
+ {
+ struct
+ {
+ uint16_t lid;
+ ib_net64_t port_guid;
+ uint8_t port_num;
+
+ /*
+ * The following structure is valid only for
+ * P_KEY, Q_KEY, and M_KEY violation traps.
+ */
+ struct
+ {
+ uint8_t sl;
+ uint16_t src_lid;
+ uint16_t dest_lid;
+ union _key
+ {
+ uint16_t pkey;
+ uint32_t qkey;
+ uint64_t mkey;
+ } key;
+ uint32_t src_qp;
+ uint32_t dest_qp;
+ ib_gid_t src_gid;
+ ib_gid_t dest_gid;
+
+ } violation;
+
+ } info;
+
+ ib_net64_t sysimg_guid;
+
+ } trap;
+
+} ib_event_rec_t;
+/*******/
+
+
+/****d* Access Layer/ib_atomic_t
+* NAME
+* ib_atomic_t
+*
+* DESCRIPTION
+* Indicates atomicity levels supported by an adapter.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_atomic_t
+{
+ IB_ATOMIC_NONE,
+ IB_ATOMIC_LOCAL,
+ IB_ATOMIC_GLOBAL
+
+} ib_atomic_t;
+/*
+* VALUES
+* IB_ATOMIC_NONE
+* Atomic operations not supported.
+*
+* IB_ATOMIC_LOCAL
+* Atomic operations guaranteed between QPs of a single CA.
+*
+* IB_ATOMIC_GLOBAL
+* Atomic operations are guaranteed between CA and any other entity
+* in the system.
+*****/
+
+
+/****s* Access Layer/ib_port_cap_t
+* NAME
+* ib_port_cap_t
+*
+* DESCRIPTION
+* Indicates which management agents are currently available on the specified
+* port.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_cap
+{
+ boolean_t cm;
+ boolean_t snmp;
+ boolean_t dev_mgmt;
+ boolean_t vend;
+ boolean_t sm;
+ boolean_t sm_disable;
+ boolean_t qkey_ctr;
+ boolean_t pkey_ctr;
+ boolean_t notice;
+ boolean_t trap;
+ boolean_t apm;
+ boolean_t slmap;
+ boolean_t pkey_nvram;
+ boolean_t mkey_nvram;
+ boolean_t sysguid;
+ boolean_t dr_notice;
+ boolean_t boot_mgmt;
+ boolean_t capm_notice;
+ boolean_t reinit;
+ boolean_t ledinfo;
+ boolean_t port_active;
+
+} ib_port_cap_t;
+/*****/
+
+
+/****d* Access Layer/ib_init_type_t
+* NAME
+* ib_init_type_t
+*
+* DESCRIPTION
+* If supported by the HCA, the type of initialization requested by
+* this port before SM moves it to the active or armed state. If the
+* SM implements reinitialization, it shall set these bits to indicate
+* the type of initialization performed prior to activating the port.
+* Otherwise, these bits shall be set to 0.
+*
+* SYNOPSIS
+*/
+typedef uint8_t ib_init_type_t;
+#define IB_INIT_TYPE_NO_LOAD 0x01
+#define IB_INIT_TYPE_PRESERVE_CONTENT 0x02
+#define IB_INIT_TYPE_PRESERVE_PRESENCE 0x04
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE 0x08
+/*****/
+
+
+/****s* Access Layer/ib_port_attr_mod_t
+* NAME
+* ib_port_attr_mod_t
+*
+* DESCRIPTION
+* Port attributes that may be modified.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr_mod
+{
+ ib_port_cap_t cap;
+ uint16_t pkey_ctr;
+ uint16_t qkey_ctr;
+
+ ib_init_type_t init_type;
+ ib_net64_t system_image_guid;
+
+} ib_port_attr_mod_t;
+/*
+* SEE ALSO
+* ib_port_cap_t
+*****/
+
+
+/****s* Access Layer/ib_port_attr_t
+* NAME
+* ib_port_attr_t
+*
+* DESCRIPTION
+* Information about a port on a given channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr
+{
+ ib_net64_t port_guid;
+ uint8_t port_num;
+ uint8_t mtu;
+ uint64_t max_msg_size;
+ ib_net16_t lid;
+ uint8_t lmc;
+
+ /*
+ * LinkWidthSupported as defined in PortInfo. Required to calculate
+ * inter-packet delay (a.k.a. static rate).
+ */
+ uint8_t link_width_supported;
+
+ uint16_t max_vls;
+
+ ib_net16_t sm_lid;
+ uint8_t sm_sl;
+ uint8_t link_state;
+
+ ib_init_type_t init_type_reply; /* Optional */
+
+ /*
+ * subnet_timeout:
+ * The maximum expected subnet propagation delay to reach any port on
+ * the subnet. This value also determines the rate at which traps can
+ * be generated from this node.
+ *
+ * timeout = 4.096 microseconds * 2^subnet_timeout
+ */
+ uint8_t subnet_timeout;
+
+ ib_port_cap_t cap;
+ uint16_t pkey_ctr;
+ uint16_t qkey_ctr;
+
+ uint16_t num_gids;
+ uint16_t num_pkeys;
+ /*
+ * Pointers at the end of the structure to allow doing a simple
+ * memory comparison of contents up to the first pointer.
+ */
+ ib_gid_t *p_gid_table;
+ ib_net16_t *p_pkey_table;
+
+} ib_port_attr_t;
+/*
+* SEE ALSO
+* uint8_t, ib_port_cap_t, ib_link_states_t
+*****/
+
+
+/****s* Access Layer/ib_ca_attr_t
+* NAME
+* ib_ca_attr_t
+*
+* DESCRIPTION
+* Information about a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_attr
+{
+ ib_net64_t ca_guid;
+
+ uint32_t vend_id;
+ uint16_t dev_id;
+ uint16_t revision;
+
+ /*
+ * Total size of the ca attributes in bytes
+ */
+ uint32_t size;
+ uint32_t max_qps;
+ uint32_t max_wrs;
+
+ uint32_t max_sges;
+ uint32_t max_rd_sges;
+
+ uint32_t max_cqs;
+ uint32_t max_cqes;
+
+ uint32_t max_pds;
+
+ uint32_t init_regions;
+ uint64_t init_region_size;
+
+ uint32_t init_windows;
+ uint32_t max_addr_handles;
+
+ uint32_t max_partitions;
+
+ ib_atomic_t atomicity;
+
+ uint8_t max_qp_resp_res;
+ uint8_t max_eec_resp_res;
+ uint8_t max_resp_res;
+
+ uint8_t max_qp_init_depth;
+ uint8_t max_eec_init_depth;
+
+ uint32_t max_eecs;
+ uint32_t max_rdds;
+
+ uint32_t max_ipv6_qps;
+ uint32_t max_ether_qps;
+
+ uint32_t max_mcast_grps;
+ uint32_t max_mcast_qps;
+ uint32_t max_qps_per_mcast_grp;
+
+ /*
+ * local_ack_delay:
+ * Specifies the maximum time interval between the local CA receiving
+ * a message and the transmission of the associated ACK or NAK.
+ *
+ * timeout = 4.096 microseconds * 2^local_ack_delay
+ */
+ uint8_t local_ack_delay;
+
+ boolean_t bad_pkey_ctr_support;
+ boolean_t bad_qkey_ctr_support;
+ boolean_t raw_mcast_support;
+ boolean_t apm_support;
+ boolean_t av_port_check;
+ boolean_t change_primary_port;
+ boolean_t modify_wr_depth;
+ boolean_t current_qp_state_support;
+ boolean_t shutdown_port_capability;
+ boolean_t init_type_support;
+ boolean_t port_active_event_support;
+ boolean_t system_image_guid_support;
+ boolean_t hw_agents;
+
+ ib_net64_t system_image_guid;
+
+ uint32_t num_page_sizes;
+ uint8_t num_ports;
+
+ uint32_t *p_page_size;
+ ib_port_attr_t *p_port_attr;
+
+} ib_ca_attr_t;
+/*
+* FIELDS
+* ca_guid
+* GUID for this adapter.
+*
+* vend_id
+* IEEE vendor ID for this adapter
+*
+* dev_id
+* Device ID of this adapter. (typically from PCI device ID)
+*
+* revision
+* Revision ID of this adapter
+*
+* size
+* Total size in bytes for the HCA attributes. This size includes total
+* size required for all the variable members of the structure. If a
+* vendor requires to pass vendor specific fields beyond this structure,
+* the HCA vendor can choose to report a larger size. If a vendor is
+* reporting extended vendor specific features, they should also provide
+* appropriate access functions to aid with the required interpretation.
+*
+* max_qps
+* Maximum number of QP's supported by this HCA.
+*
+* max_wrs
+* Maximum number of work requests supported by this HCA.
+*
+* max_sges
+* Maximum number of scatter gather elements supported per work request.
+*
+* max_rd_sges
+* Maximum number of scatter gather elements supported for READ work
+* requests for a Reliable Datagram QP. This value must be zero if RD
+* service is not supported.
+*
+* max_cqs
+* Maximum number of Completion Queues supported.
+*
+* max_cqes
+* Maximum number of CQ elements supported per CQ.
+*
+* max_pds
+* Maximum number of protection domains supported.
+*
+* init_regions
+* Initial number of memory regions supported. These are only informative
+* values. HCA vendors can extended and grow these limits on demand.
+*
+* init_region_size
+* Initial limit on the size of the registered memory region.
+*
+* init_windows
+* Initial number of window entries supported.
+*
+* max_addr_handles
+* Maximum number of address handles supported.
+*
+* max_partitions
+* Maximum number of partitions supported.
+*
+* atomicity
+* Indicates level of atomic operations supported by this HCA.
+*
+* max_qp_resp_res
+* max_eec_resp_res
+* Maximum limit on number of responder resources for incoming RDMA
+* operations, on QPs and EEC's respectively.
+*
+* max_resp_res
+* Maximum number of responder resources per HCA, with this HCA used as
+* the target.
+*
+* max_qp_init_depth
+* max_eec_init_depth
+* Maximimum initiator depth per QP or EEC for initiating RDMA reads and
+* atomic operations.
+*
+* max_eecs
+* Maximimum number of EEC's supported by the HCA.
+*
+* max_rdds
+* Maximum number of Reliable datagram domains supported.
+*
+* max_ipv6_qps
+* max_ether_qps
+* Maximum number of IPV6 and raw ether QP's supported by this HCA.
+*
+* max_mcast_grps
+* Maximum number of multicast groups supported.
+*
+* max_mcast_qps
+* Maximum number of QP's that can support multicast operations.
+*
+* max_qps_per_mcast_grp
+* Maximum number of multicast QP's per multicast group.
+*
+* local_ack_delay
+* Specifies the maximum time interval between the local CA receiving
+* a message and the transmission of the associated ACK or NAK.
+* timeout = 4.096 microseconds * 2^local_ack_delay
+*
+* bad_pkey_ctr_support
+* bad_qkey_ctr_support
+* Indicates support for the bad pkey and qkey counters.
+*
+* raw_mcast_support
+* Indicates support for raw packet multicast.
+*
+* apm_support
+* Indicates support for Automatic Path Migration.
+*
+* av_port_check
+* Indicates ability to check port number in address handles.
+*
+* change_primary_port
+* Indicates ability to change primary port for a QP or EEC during a
+* SQD->RTS transition.
+*
+* modify_wr_depth
+* Indicates ability to modify QP depth during a modify QP operation.
+* Check the verb specification for permitted states.
+*
+* current_qp_state_support
+* Indicates ability of the HCA to support the current QP state modifier
+* during a modify QP operation.
+*
+* shutdown_port_capability
+* Shutdown port capability support indicator.
+*
+* init_type_support
+* Indicates init_type_reply and ability to set init_type is supported.
+*
+* port_active_event_support
+* Port active event support indicator.
+*
+* system_image_guid_support
+* System image GUID support indicator.
+*
+* hw_agents
+* Indicates SMA is implemented in HW.
+*
+* system_image_guid
+* Optional system image GUID. This field is valid only if the
+* system_image_guid_support flag is set.
+*
+* num_page_sizes
+* Indicates support for different page sizes supported by the HCA.
+* The variable size array can be obtained from p_page_size.
+*
+* num_ports
+* Number of physical ports supported on this HCA.
+*
+* p_page_size
+* Array holding different page size supported.
+*
+* p_port_attr
+* Array holding port attributes.
+*
+* NOTES
+* This structure contains the attributes of a channel adapter. Users must
+* call ib_copy_ca_attr to copy the contents of this structure to a new
+* memory region.
+*
+* SEE ALSO
+* ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr
+*****/
+
+/****f* Access layer/ib_copy_ca_attr
+* NAME
+* ib_copy_ca_attr
+*
+* DESCRIPTION
+* Copies CA attributes.
+*
+* SYNOPSIS
+*/
+ib_ca_attr_t*
+ib_copy_ca_attr(
+ IN ib_ca_attr_t* const p_dest,
+ IN const ib_ca_attr_t* const p_src );
+/*
+* PARAMETERS
+* p_dest
+* Pointer to the buffer that is the destination of the copy.
+*
+* p_src
+* Pointer to the CA attributes to copy.
+*
+* RETURN VALUE
+* Pointer to the copied CA attributes.
+*
+* NOTES
+* The buffer pointed to by the p_dest parameter must be at least the size
+* specified in the size field of the buffer pointed to by p_src.
+*
+* SEE ALSO
+* ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr
+*****/
+
+
+/****s* Access Layer/ib_av_attr_t
+* NAME
+* ib_av_attr_t
+*
+* DESCRIPTION
+* IBA address vector.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_av_attr
+{
+ uint8_t port_num;
+
+ uint8_t sl;
+ ib_net16_t dlid;
+
+ boolean_t grh_valid;
+ ib_grh_t grh;
+ uint8_t static_rate;
+ uint8_t path_bits;
+
+ struct _av_conn
+ {
+ uint8_t path_mtu;
+ uint8_t local_ack_timeout;
+ uint8_t seq_err_retry_cnt;
+ uint8_t rnr_retry_cnt;
+
+ } conn;
+
+} ib_av_attr_t;
+/*
+* SEE ALSO
+* ib_gid_t
+*****/
+
+
+/****d* Access Layer/ib_qp_type_t
+* NAME
+* ib_qp_type_t
+*
+* DESCRIPTION
+* Indicates the type of queue pair being created.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_qp_type
+{
+ IB_QPT_RELIABLE_CONN = 0, /* Matches CM REQ transport type */
+ IB_QPT_UNRELIABLE_CONN = 1, /* Matches CM REQ transport type */
+ IB_QPT_RELIABLE_DGRM = 2, /* Matches CM REQ transport type */
+ IB_QPT_UNRELIABLE_DGRM,
+ IB_QPT_QP0,
+ IB_QPT_QP1,
+ IB_QPT_RAW_IPV6,
+ IB_QPT_RAW_ETHER,
+ IB_QPT_MAD, /* InfiniBand Access Layer */
+ IB_QPT_QP0_ALIAS, /* InfiniBand Access Layer */
+ IB_QPT_QP1_ALIAS /* InfiniBand Access Layer */
+
+} ib_qp_type_t;
+/*
+* VALUES
+* IB_QPT_RELIABLE_CONN
+* Reliable, connected queue pair.
+*
+* IB_QPT_UNRELIABLE_CONN
+* Unreliable, connected queue pair.
+*
+* IB_QPT_RELIABLE_DGRM
+* Reliable, datagram queue pair.
+*
+* IB_QPT_UNRELIABLE_DGRM
+* Unreliable, datagram queue pair.
+*
+* IB_QPT_QP0
+* Queue pair 0.
+*
+* IB_QPT_QP1
+* Queue pair 1.
+*
+* IB_QPT_RAW_DGRM
+* Raw datagram queue pair.
+*
+* IB_QPT_RAW_IPV6
+* Raw IP version 6 queue pair.
+*
+* IB_QPT_RAW_ETHER
+* Raw Ethernet queue pair.
+*
+* IB_QPT_MAD
+* Unreliable, datagram queue pair that will send and receive management
+* datagrams with assistance from the access layer.
+*
+* IB_QPT_QP0_ALIAS
+* Alias to queue pair 0. Aliased QPs can only be created on an aliased
+* protection domain.
+*
+* IB_QPT_QP1_ALIAS
+* Alias to queue pair 1. Aliased QPs can only be created on an aliased
+* protection domain.
+*****/
+
+
+/****d* Access Layer/ib_access_t
+* NAME
+* ib_access_t
+*
+* DESCRIPTION
+* Indicates the type of access is permitted on resources such as QPs,
+* memory regions and memory windows.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_access_t;
+#define IB_AC_RDMA_READ 0x00000001
+#define IB_AC_RDMA_WRITE 0x00000002
+#define IB_AC_ATOMIC 0x00000004
+#define IB_AC_LOCAL_WRITE 0x00000008
+#define IB_AC_MW_BIND 0x00000010
+/*
+* NOTES
+* Users may combine access rights using a bit-wise or operation to specify
+* additional access. For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants
+* RDMA read and write access.
+*****/
+
+
+/****d* Access Layer/ib_qp_state_t
+* NAME
+* ib_qp_state_t
+*
+* DESCRIPTION
+* Indicates or sets the state of a queue pair. The current state of a queue
+* pair is returned through the ib_qp_query call and set via the
+* ib_qp_modify call.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_state_t;
+#define IB_QPS_RESET 0x00000001
+#define IB_QPS_INIT 0x00000002
+#define IB_QPS_RTR 0x00000004
+#define IB_QPS_RTS 0x00000008
+#define IB_QPS_SQD 0x00000010
+#define IB_QPS_SQD_DRAINING 0x00000030
+#define IB_QPS_SQD_DRAINED 0x00000050
+#define IB_QPS_SQERR 0x00000080
+#define IB_QPS_ERROR 0x00000100
+#define IB_QPS_TIME_WAIT 0xDEAD0000 /* InfiniBand Access Layer */
+/*****/
+
+
+/****d* Access Layer/ib_apm_state_t
+* NAME
+* ib_apm_state_t
+*
+* DESCRIPTION
+* The current automatic path migration state of a queue pair
+*
+* SYNOPSIS
+*/
+typedef enum _ib_apm_state
+{
+ IB_APM_MIGRATED = 1,
+ IB_APM_REARM,
+ IB_APM_ARMED
+
+} ib_apm_state_t;
+/*****/
+
+
+/****s* Access Layer/ib_qp_create_t
+* NAME
+* ib_qp_create_t
+*
+* DESCRIPTION
+* Attributes used to initialize a queue pair at creation time.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_create
+{
+ ib_qp_type_t qp_type;
+
+ ib_rdd_handle_t h_rdd;
+
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+ uint32_t sq_sge;
+ uint32_t rq_sge;
+
+ ib_cq_handle_t h_sq_cq;
+ ib_cq_handle_t h_rq_cq;
+
+ boolean_t sq_signaled;
+
+} ib_qp_create_t;
+/*
+* FIELDS
+* type
+* Specifies the type of queue pair to create.
+*
+* h_rdd
+* A handle to a reliable datagram domain to associate with the queue
+* pair. This field is ignored if the queue pair is not a reliable
+* datagram type queue pair.
+*
+* sq_depth
+* Indicates the requested maximum number of work requests that may be
+* outstanding on the queue pair's send queue. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* rq_depth
+* Indicates the requested maximum number of work requests that may be
+* outstanding on the queue pair's receive queue. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* sq_sge
+* Indicates the maximum number scatter-gather elements that may be
+* given in a send work request. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* rq_sge
+* Indicates the maximum number scatter-gather elements that may be
+* given in a receive work request. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* h_sq_cq
+* A handle to the completion queue that will be used to report send work
+* request completions. This handle must be NULL if the type is
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+* h_rq_cq
+* A handle to the completion queue that will be used to report receive
+* work request completions. This handle must be NULL if the type is
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+* sq_signaled
+* A flag that is used to indicate whether the queue pair will signal
+* an event upon completion of a send work request. If set to
+* TRUE, send work requests will always generate a completion
+* event. If set to FALSE, a completion event will only be
+* generated if the send_opt field of the send work request has the
+* IB_SEND_OPT_SIGNALED flag set.
+*
+* SEE ALSO
+* ib_qp_type_t, ib_qp_attr_t
+*****/
+
+
+/****s* Access Layer/ib_qp_attr_t
+* NAME
+* ib_qp_attr_t
+*
+* DESCRIPTION
+* Queue pair attributes returned through ib_query_qp.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_attr
+{
+ ib_pd_handle_t h_pd;
+ ib_qp_type_t qp_type;
+ ib_access_t access_ctrl;
+ uint16_t pkey_index;
+
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+ uint32_t sq_sge;
+ uint32_t rq_sge;
+ uint8_t init_depth;
+ uint8_t resp_res;
+
+ ib_cq_handle_t h_sq_cq;
+ ib_cq_handle_t h_rq_cq;
+ ib_rdd_handle_t h_rdd;
+
+ boolean_t sq_signaled;
+
+ ib_qp_state_t state;
+ ib_net32_t num;
+ ib_net32_t dest_num;
+ ib_net32_t qkey;
+
+ ib_net32_t sq_psn;
+ ib_net32_t rq_psn;
+
+ uint8_t primary_port;
+ uint8_t alternate_port;
+ ib_av_attr_t primary_av;
+ ib_av_attr_t alternate_av;
+ ib_apm_state_t apm_state;
+
+} ib_qp_attr_t;
+/*
+* FIELDS
+* h_pd
+* This is a handle to a protection domain associated with the queue
+* pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM.
+*
+* NOTES
+* Other fields are defined by the Infiniband specification.
+*
+* SEE ALSO
+* ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_qp_opts_t
+* NAME
+* ib_qp_opts_t
+*
+* DESCRIPTION
+* Optional fields supplied in the modify QP operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_opts_t;
+#define IB_MOD_QP_ALTERNATE_AV 0x00000001
+#define IB_MOD_QP_PKEY 0x00000002
+#define IB_MOD_QP_APM_STATE 0x00000004
+#define IB_MOD_QP_PRIMARY_AV 0x00000008
+#define IB_MOD_QP_RNR_NAK_TIMEOUT 0x00000010
+#define IB_MOD_QP_RESP_RES 0x00000020
+#define IB_MOD_QP_INIT_DEPTH 0x00000040
+#define IB_MOD_QP_PRIMARY_PORT 0x00000080
+#define IB_MOD_QP_ACCESS_CTRL 0x00000100
+#define IB_MOD_QP_QKEY 0x00000200
+#define IB_MOD_QP_SQ_DEPTH 0x00000400
+#define IB_MOD_QP_RQ_DEPTH 0x00000800
+#define IB_MOD_QP_CURRENT_STATE 0x00001000
+#define IB_MOD_QP_RETRY_CNT 0x00002000
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT 0x00004000
+#define IB_MOD_QP_RNR_RETRY_CNT 0x00008000
+
+/*
+* SEE ALSO
+* ib_qp_mod_t
+*****/
+
+
+/****s* Access Layer/ib_qp_mod_t
+* NAME
+* ib_qp_mod_t
+*
+* DESCRIPTION
+* Information needed to change the state of a queue pair through the
+* ib_modify_qp call.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_mod
+{
+ ib_qp_state_t req_state;
+
+ union _qp_state
+ {
+ struct _qp_reset
+ {
+ /*
+ * Time, in milliseconds, that the QP needs to spend in the
+ * time wait state before being reused.
+ */
+ uint32_t timewait;
+
+ } reset;
+
+ struct _qp_init
+ {
+ ib_qp_opts_t opts;
+ uint8_t primary_port;
+ ib_net32_t qkey;
+ uint16_t pkey_index;
+ ib_access_t access_ctrl;
+
+ } init;
+
+ struct _qp_rtr
+ {
+ ib_net32_t rq_psn;
+ ib_net32_t dest_qp;
+ ib_av_attr_t primary_av;
+ uint8_t resp_res;
+
+ ib_qp_opts_t opts;
+ ib_av_attr_t alternate_av;
+ ib_net32_t qkey;
+ uint16_t pkey_index;
+ ib_access_t access_ctrl;
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+ uint8_t rnr_nak_timeout;
+
+ } rtr;
+
+ struct _qp_rts
+ {
+ ib_net32_t sq_psn;
+ uint8_t retry_cnt;
+ uint8_t rnr_retry_cnt;
+ uint8_t rnr_nak_timeout;
+ uint8_t local_ack_timeout;
+ uint8_t init_depth;
+
+ ib_qp_opts_t opts;
+ ib_qp_state_t current_state;
+ ib_net32_t qkey;
+ ib_access_t access_ctrl;
+ uint8_t resp_res;
+
+ ib_av_attr_t primary_av;
+ ib_av_attr_t alternate_av;
+
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+
+ ib_apm_state_t apm_state;
+ uint8_t primary_port;
+ uint16_t pkey_index;
+
+ } rts;
+
+ struct _qp_sqd
+ {
+ boolean_t sqd_event;
+
+ } sqd;
+
+ } state;
+
+} ib_qp_mod_t;
+/*
+* SEE ALSO
+* ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****s* Access Layer/ib_eec_attr_t
+* NAME
+* ib_eec_attr_t
+*
+* DESCRIPTION
+* Information about an end-to-end context.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_attr
+{
+ ib_qp_state_t state;
+ ib_rdd_handle_t h_rdd;
+ ib_net32_t local_eecn;
+
+ ib_net32_t sq_psn;
+ ib_net32_t rq_psn;
+ uint8_t primary_port;
+ uint16_t pkey_index;
+ uint32_t resp_res;
+ ib_net32_t remote_eecn;
+ uint32_t init_depth;
+ uint32_t dest_num; // ??? What is this?
+ ib_av_attr_t primary_av;
+ ib_av_attr_t alternate_av;
+ ib_apm_state_t apm_state;
+
+} ib_eec_attr_t;
+/*
+* SEE ALSO
+* ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_eec_opts_t
+* NAME
+* ib_eec_opts_t
+*
+* DESCRIPTION
+* Optional fields supplied in the modify EEC operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_eec_opts_t;
+#define IB_MOD_EEC_ALTERNATE_AV 0x00000001
+#define IB_MOD_EEC_PKEY 0x00000002
+#define IB_MOD_EEC_APM_STATE 0x00000004
+#define IB_MOD_EEC_PRIMARY_AV 0x00000008
+#define IB_MOD_EEC_RNR 0x00000010
+#define IB_MOD_EEC_RESP_RES 0x00000020
+#define IB_MOD_EEC_OUTSTANDING 0x00000040
+#define IB_MOD_EEC_PRIMARY_PORT 0x00000080
+/*
+* NOTES
+*
+*
+*****/
+
+/****s* Access Layer/ib_eec_mod_t
+* NAME
+* ib_eec_mod_t
+*
+* DESCRIPTION
+* Information needed to change the state of an end-to-end context through
+* the ib_modify_eec function.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_mod
+{
+ ib_qp_state_t req_state;
+
+ union _eec_state
+ {
+ struct _eec_init
+ {
+ uint8_t primary_port;
+ uint16_t pkey_index;
+
+ } init;
+
+ struct _eec_rtr
+ {
+ ib_net32_t rq_psn;
+ ib_net32_t remote_eecn;
+ ib_av_attr_t primary_av;
+ uint8_t resp_res;
+
+ ib_eec_opts_t opts;
+ ib_av_attr_t alternate_av;
+ uint16_t pkey_index;
+
+ } rtr;
+
+ struct _eec_rts
+ {
+ ib_net32_t sq_psn;
+ uint8_t retry_cnt;
+ uint8_t rnr_retry_cnt;
+ uint8_t local_ack_timeout;
+ uint8_t init_depth;
+
+ ib_eec_opts_t opts;
+ ib_av_attr_t alternate_av;
+ ib_apm_state_t apm_state;
+
+ ib_av_attr_t primary_av;
+ uint16_t pkey_index;
+ uint8_t primary_port;
+
+ } rts;
+
+ struct _eec_sqd
+ {
+ boolean_t sqd_event;
+
+ } sqd;
+
+ } state;
+
+} ib_eec_mod_t;
+/*
+* SEE ALSO
+* ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_wr_type_t
+* NAME
+* ib_wr_type_t
+*
+* DESCRIPTION
+* Identifies the type of work request posted to a queue pair.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wr_type_t
+{
+ WR_SEND = 1,
+ WR_RDMA_WRITE,
+ WR_RDMA_READ,
+ WR_COMPARE_SWAP,
+ WR_FETCH_ADD
+
+} ib_wr_type_t;
+/*****/
+
+
+/****s* Access Layer/ib_local_ds_t
+* NAME
+* ib_local_ds_t
+*
+* DESCRIPTION
+* Local data segment information referenced by send and receive work
+* requests. This is used to specify local data buffers used as part of a
+* work request.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_local_ds
+{
+ void *vaddr;
+ uint32_t length;
+ uint32_t lkey;
+
+} ib_local_ds_t;
+/*****/
+
+
+/****d* Access Layer/ib_send_opt_t
+* NAME
+* ib_send_opt_t
+*
+* DESCRIPTION
+* Optional flags used when posting send work requests. These flags
+* indicate specific processing for the send operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_send_opt_t;
+#define IB_SEND_OPT_IMMEDIATE 0x00000001
+#define IB_SEND_OPT_FENCE 0x00000002
+#define IB_SEND_OPT_SIGNALED 0x00000004
+#define IB_SEND_OPT_SOLICITED 0x00000008
+#define IB_SEND_OPT_INLINE 0x00000010
+#define IB_SEND_OPT_LOCAL 0x00000020
+#define IB_SEND_OPT_VEND_MASK 0xFFFF0000
+
+
+/*
+* VALUES
+* The following flags determine the behavior of a work request when
+* posted to the send side.
+*
+* IB_SEND_OPT_IMMEDIATE
+* Send immediate data with the given request.
+*
+* IB_SEND_OPT_FENCE
+* The operation is fenced. Complete all pending send operations before
+* processing this request.
+*
+* IB_SEND_OPT_SIGNALED
+* If the queue pair is configured for signaled completion, then
+* generate a completion queue entry when this request completes.
+*
+* IB_SEND_OPT_SOLICITED
+* Set the solicited bit on the last packet of this request.
+*
+* IB_SEND_OPT_INLINE
+* Indicates that the requested send data should be copied into a VPD
+* owned data buffer. This flag permits the user to issue send operations
+* without first needing to register the buffer(s) associated with the
+* send operation. Verb providers that support this operation may place
+* vendor specific restrictions on the size of send operation that may
+* be performed as inline.
+*
+*
+* IB_SEND_OPT_LOCAL
+* Indicates that a sent MAD request should be given to the local VPD for
+* processing. MADs sent using this option are not placed on the wire.
+* This send option is only valid for MAD send operations.
+*
+*
+* IB_SEND_OPT_VEND_MASK
+* This mask indicates bits reserved in the send options that may be used
+* by the verbs provider to indicate vendor specific options. Bits set
+* in this area of the send options are ignored by the Access Layer, but
+* may have specific meaning to the underlying VPD.
+*
+*****/
+
+
+/****s* Access Layer/ib_send_wr_t
+* NAME
+* ib_send_wr_t
+*
+* DESCRIPTION
+* Information used to submit a work request to the send queue of a queue
+* pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_send_wr
+{
+ struct _ib_send_wr *p_next;
+ uint64_t wr_id;
+ ib_wr_type_t wr_type;
+ ib_send_opt_t send_opt;
+ uint32_t num_ds;
+ ib_local_ds_t *ds_array;
+ ib_net32_t immediate_data;
+
+ union _send_dgrm
+ {
+ struct _send_ud
+ {
+ ib_net32_t remote_qp;
+ ib_net32_t remote_qkey;
+ ib_av_handle_t h_av;
+
+ } ud;
+
+ struct _send_rd
+ {
+ ib_net32_t remote_qp;
+ ib_net32_t remote_qkey;
+ ib_net32_t eecn;
+
+ } rd;
+
+ struct _send_raw_ether
+ {
+ ib_net16_t dest_lid;
+ uint8_t path_bits;
+ uint8_t sl;
+ uint8_t max_static_rate;
+ ib_net16_t ether_type;
+
+ } raw_ether;
+
+ struct _send_raw_ipv6
+ {
+ ib_net16_t dest_lid;
+ uint8_t path_bits;
+ uint8_t sl;
+ uint8_t max_static_rate;
+
+ } raw_ipv6;
+
+ } dgrm;
+
+ struct _send_remote_ops
+ {
+ uint64_t vaddr;
+ uint32_t rkey;
+
+ ib_net64_t atomic1;
+ ib_net64_t atomic2;
+
+ } remote_ops;
+
+} ib_send_wr_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work requests together. This permits multiple
+* work requests to be posted to a queue pair through a single function
+* call. This value is set to NULL to mark the end of the chain.
+*
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* wr_type
+* The type of work request being submitted to the send queue.
+*
+* send_opt
+* Optional send control parameters.
+*
+* num_ds
+* Number of local data segments specified by this work request.
+*
+* ds_array
+* A reference to an array of local data segments used by the send
+* operation.
+*
+* immediate_data
+* 32-bit field sent as part of a message send or RDMA write operation.
+* This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE
+* has been set.
+*
+* dgrm.ud.remote_qp
+* Identifies the destination queue pair of an unreliable datagram send
+* operation.
+*
+* dgrm.ud.remote_qkey
+* The qkey for the destination queue pair.
+*
+* dgrm.ud.h_av
+* An address vector that specifies the path information used to route
+* the outbound datagram to the destination queue pair.
+*
+* dgrm.rd.remote_qp
+* Identifies the destination queue pair of a reliable datagram send
+* operation.
+*
+* dgrm.rd.remote_qkey
+* The qkey for the destination queue pair.
+*
+* dgrm.rd.eecn
+* The local end-to-end context number to use with the reliable datagram
+* send operation.
+*
+* dgrm.raw_ether.dest_lid
+* The destination LID that will receive this raw ether send.
+*
+* dgrm.raw_ether.path_bits
+* path bits...
+*
+* dgrm.raw_ether.sl
+* service level...
+*
+* dgrm.raw_ether.max_static_rate
+* static rate...
+*
+* dgrm.raw_ether.ether_type
+* ether type...
+*
+* dgrm.raw_ipv6.dest_lid
+* The destination LID that will receive this raw ether send.
+*
+* dgrm.raw_ipv6.path_bits
+* path bits...
+*
+* dgrm.raw_ipv6.sl
+* service level...
+*
+* dgrm.raw_ipv6.max_static_rate
+* static rate...
+*
+* remote_ops.vaddr
+* The registered virtual memory address of the remote memory to access
+* with an RDMA or atomic operation.
+*
+* remote_ops.rkey
+* The rkey associated with the specified remote vaddr. This data must
+* be presented exactly as obtained from the remote node. No swapping
+* of data must be performed.
+*
+* atomic1
+* The first operand for an atomic operation.
+*
+* atomic2
+* The second operand for an atomic operation.
+*
+* NOTES
+* The format of data sent over the fabric is user-defined and is considered
+* opaque to the access layer. The sole exception to this are MADs posted
+* to a MAD QP service. MADs are expected to match the format defined by
+* the Infiniband specification and must be in network-byte order when posted
+* to the MAD QP service.
+*
+* SEE ALSO
+* ib_wr_type_t, ib_local_ds_t, ib_send_opt_t
+*****/
+
+
+/****s* Access Layer/ib_recv_wr_t
+* NAME
+* ib_recv_wr_t
+*
+* DESCRIPTION
+* Information used to submit a work request to the receive queue of a queue
+* pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_recv_wr
+{
+ struct _ib_recv_wr *p_next;
+ uint64_t wr_id;
+ uint32_t num_ds;
+ ib_local_ds_t *ds_array;
+
+} ib_recv_wr_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work requests together. This permits multiple
+* work requests to be posted to a queue pair through a single function
+* call. This value is set to NULL to mark the end of the chain.
+*
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* num_ds
+* Number of local data segments specified by this work request.
+*
+* ds_array
+* A reference to an array of local data segments used by the send
+* operation.
+*
+* SEE ALSO
+* ib_local_ds_t
+*****/
+
+
+/****s* Access Layer/ib_bind_wr_t
+* NAME
+* ib_bind_wr_t
+*
+* DESCRIPTION
+* Information used to submit a memory window bind work request to the send
+* queue of a queue pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_bind_wr
+{
+ uint64_t wr_id;
+ ib_send_opt_t send_opt;
+
+ ib_mr_handle_t h_mr;
+ ib_access_t access_ctrl;
+ uint32_t current_rkey;
+
+ ib_local_ds_t local_ds;
+
+} ib_bind_wr_t;
+/*
+* FIELDS
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* send_opt
+* Optional send control parameters.
+*
+* h_mr
+* Handle to the memory region to which this window is being bound.
+*
+* access_ctrl
+* Access rights for this memory window.
+*
+* current_rkey
+* The current rkey assigned to this window for remote access.
+*
+* local_ds
+* A reference to a local data segment used by the bind operation.
+*
+* SEE ALSO
+* ib_send_opt_t, ib_access_t, ib_local_ds_t
+*****/
+
+
+/****d* Access Layer/ib_wc_status_t
+* NAME
+* ib_wc_status_t
+*
+* DESCRIPTION
+* Indicates the status of a completed work request. These VALUES are
+* returned to the user when retrieving completions. Note that success is
+* identified as IB_WCS_SUCCESS, which is always zero.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_status_t
+{
+ IB_WCS_SUCCESS,
+ IB_WCS_LOCAL_LEN_ERR,
+ IB_WCS_LOCAL_OP_ERR,
+ IB_WCS_LOCAL_EEC_OP_ERR,
+ IB_WCS_LOCAL_PROTECTION_ERR,
+ IB_WCS_WR_FLUSHED_ERR,
+ IB_WCS_MEM_WINDOW_BIND_ERR,
+ IB_WCS_REM_ACCESS_ERR,
+ IB_WCS_REM_OP_ERR,
+ IB_WCS_RNR_RETRY_ERR,
+ IB_WCS_TIMEOUT_RETRY_ERR,
+ IB_WCS_REM_INVALID_REQ_ERR,
+ IB_WCS_REM_INVALID_RD_REQ_ERR,
+ IB_WCS_INVALID_EECN,
+ IB_WCS_INVALID_EEC_STATE,
+ IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */
+ IB_WCS_CANCELED, /* InfiniBand Access Layer */
+ IB_WCS_UNKNOWN /* Must be last. */
+
+} ib_wc_status_t;
+/*
+* VALUES
+* IB_WCS_SUCCESS
+* Work request completed successfully.
+*
+* IB_WCS_MAD
+* The completed work request was associated with a managmenet datagram
+* that requires post processing. The MAD will be returned to the user
+* through a callback once all post processing has completed.
+*
+* IB_WCS_LOCAL_LEN_ERR
+* Generated for a work request posted to the send queue when the
+* total of the data segment lengths exceeds the message length of the
+* channel. Generated for a work request posted to the receive queue when
+* the total of the data segment lengths is too small for a
+* valid incoming message.
+*
+* IB_WCS_LOCAL_OP_ERR
+* An internal QP consistency error was generated while processing this
+* work request. This may indicate that the QP was in an incorrect state
+* for the requested operation.
+*
+* IB_WCS_LOCAL_EEC_OP_ERR
+* An internal EEC consistency error was generated while processing
+* this work request. This may indicate that the EEC was in an incorrect
+* state for the requested operation.
+*
+* IB_WCS_LOCAL_PROTECTION_ERR
+* The data segments of the locally posted work request did not refer to
+* a valid memory region. The memory may not have been properly
+* registered for the requested operation.
+*
+* IB_WCS_WR_FLUSHED_ERR
+* The work request was flushed from the QP before being completed.
+*
+* IB_WCS_MEM_WINDOW_BIND_ERR
+* A memory window bind operation failed due to insufficient access
+* rights.
+*
+* IB_WCS_REM_ACCESS_ERR,
+* A protection error was detected at the remote node for a RDMA or atomic
+* operation.
+*
+* IB_WCS_REM_OP_ERR,
+* The operation could not be successfully completed at the remote node.
+* This may indicate that the remote QP was in an invalid state or
+* contained an invalid work request.
+*
+* IB_WCS_RNR_RETRY_ERR,
+* The RNR retry count was exceeded while trying to send this message.
+*
+* IB_WCS_TIMEOUT_RETRY_ERR
+* The local transport timeout counter expired while trying to send this
+* message.
+*
+* IB_WCS_REM_INVALID_REQ_ERR,
+* The remote node detected an invalid message on the channel. This error
+* is usually a result of one of the following:
+* - The operation was not supported on receive queue.
+* - There was insufficient buffers to receive a new RDMA request.
+* - There was insufficient buffers to receive a new atomic operation.
+* - An RDMA request was larger than 2^31 bytes.
+*
+* IB_WCS_REM_INVALID_RD_REQ_ERR,
+* Responder detected an invalid RD message. This may be the result of an
+* invalid qkey or an RDD mismatch.
+*
+* IB_WCS_INVALID_EECN
+* An invalid EE context number was detected.
+*
+* IB_WCS_INVALID_EEC_STATE
+* The EEC was in an invalid state for the specified request.
+*
+* IB_WCS_UNMATCHED_RESPONSE
+* A response MAD was received for which there was no matching send. The
+* send operation may have been canceled by the user or may have timed
+* out.
+*
+* IB_WCS_CANCELED
+* The completed work request was canceled by the user.
+*****/
+
+
+AL_EXPORT const char* ib_wc_status_str[];
+
+
+/****f* IBA Base: Types/ib_get_wc_status_str
+* NAME
+* ib_get_wc_status_str
+*
+* DESCRIPTION
+* Returns a string for the specified work completion status.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char* AL_API
+ib_get_wc_status_str(
+ IN ib_wc_status_t wc_status )
+{
+ if( wc_status > IB_WCS_UNKNOWN )
+ wc_status = IB_WCS_UNKNOWN;
+ return( ib_wc_status_str[wc_status] );
+}
+/*
+* PARAMETERS
+* wc_status
+* [in] work completion status value
+*
+* RETURN VALUES
+* Pointer to the work completion status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_wc_type_t
+* NAME
+* ib_wc_type_t
+*
+* DESCRIPTION
+* Indicates the type of work completion.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_type_t
+{
+ IB_WC_SEND,
+ IB_WC_RDMA_WRITE,
+ IB_WC_RECV,
+ IB_WC_RDMA_READ,
+ IB_WC_MW_BIND,
+ IB_WC_FETCH_ADD,
+ IB_WC_COMPARE_SWAP,
+ IB_WC_RECV_RDMA_WRITE
+
+} ib_wc_type_t;
+/*****/
+
+
+/****d* Access Layer/ib_recv_opt_t
+* NAME
+* ib_recv_opt_t
+*
+* DESCRIPTION
+* Indicates optional fields valid in a receive work completion.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_recv_opt_t;
+#define IB_RECV_OPT_IMMEDIATE 0x00000001
+#define IB_RECV_OPT_FORWARD 0x00000002
+#define IB_RECV_OPT_GRH_VALID 0x00000004
+#define IB_RECV_OPT_VEND_MASK 0xFFFF0000
+/*
+* VALUES
+* IB_RECV_OPT_IMMEDIATE
+* Indicates that immediate data is valid for this work completion.
+*
+* IB_RECV_OPT_FORWARD
+* Indicates that the received trap should be forwarded to the SM.
+*
+* IB_RECV_OPT_GRH_VALID
+* Indicates presence of the global route header. When set, the first
+* 40 bytes received are the GRH.
+*
+* IB_RECV_OPT_VEND_MASK
+* This mask indicates bits reserved in the receive options that may be
+* used by the verbs provider to indicate vendor specific options. Bits
+* set in this area of the receive options are ignored by the Access Layer,
+* but may have specific meaning to the underlying VPD.
+*****/
+
+
+/****s* Access Layer/ib_wc_t
+* NAME
+* ib_wc_t
+*
+* DESCRIPTION
+* Work completion information.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_wc
+{
+ struct _ib_wc *p_next;
+ uint64_t wr_id;
+ ib_wc_type_t wc_type;
+
+ uint32_t length;
+ ib_wc_status_t status;
+ uint64_t vendor_specific;
+
+ union _wc_recv
+ {
+ struct _wc_conn
+ {
+ ib_recv_opt_t recv_opt;
+ ib_net32_t immediate_data;
+
+ } conn;
+
+ struct _wc_ud
+ {
+ ib_recv_opt_t recv_opt;
+ ib_net32_t immediate_data;
+ ib_net32_t remote_qp;
+ uint16_t pkey_index;
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+
+ } ud;
+
+ struct _wc_rd
+ {
+ ib_net32_t remote_eecn;
+ ib_net32_t remote_qp;
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint32_t free_cnt;
+
+ } rd;
+
+ struct _wc_raw_ipv6
+ {
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+
+ } raw_ipv6;
+
+ struct _wc_raw_ether
+ {
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+ ib_net16_t ether_type;
+
+ } raw_ether;
+
+ } recv;
+
+} ib_wc_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work completions. This permits multiple
+* work completions to be retrieved from a completion queue through a
+* single function call. This value is set to NULL to mark the end of
+* the chain.
+*
+* wr_id
+* The 64-bit work request identifier that was specified when posting the
+* work request.
+*
+* wc_type
+* Indicates the type of work completion.
+*
+*
+* length
+* The total length of the data sent or received with the work request.
+*
+* status
+* The result of the work request.
+*
+* vendor_specific
+* HCA vendor specific information returned as part of the completion.
+*
+* recv.conn.recv_opt
+* Indicates optional fields valid as part of a work request that
+* completed on a connected (reliable or unreliable) queue pair.
+*
+* recv.conn.immediate_data
+* 32-bit field received as part of an inbound message on a connected
+* queue pair. This field is only valid if the recv_opt flag
+* IB_RECV_OPT_IMMEDIATE has been set.
+*
+* recv.ud.recv_opt
+* Indicates optional fields valid as part of a work request that
+* completed on an unreliable datagram queue pair.
+*
+* recv.ud.immediate_data
+* 32-bit field received as part of an inbound message on a unreliable
+* datagram queue pair. This field is only valid if the recv_opt flag
+* IB_RECV_OPT_IMMEDIATE has been set.
+*
+* recv.ud.remote_qp
+* Identifies the source queue pair of a received datagram.
+*
+* recv.ud.pkey_index
+* The pkey index for the source queue pair. This is valid only for
+* GSI type QP's.
+*
+* recv.ud.remote_lid
+* The source LID of the received datagram.
+*
+* recv.ud.remote_sl
+* The service level used by the source of the received datagram.
+*
+* recv.ud.path_bits
+* path bits...
+*
+* recv.rd.remote_eecn
+* The remote end-to-end context number that sent the received message.
+*
+* recv.rd.remote_qp
+* Identifies the source queue pair of a received message.
+*
+* recv.rd.remote_lid
+* The source LID of the received message.
+*
+* recv.rd.remote_sl
+* The service level used by the source of the received message.
+*
+* recv.rd.free_cnt
+* The number of available entries in the completion queue. Reliable
+* datagrams may complete out of order, so this field may be used to
+* determine the number of additional completions that may occur.
+*
+* recv.raw_ipv6.remote_lid
+* The source LID of the received message.
+*
+* recv.raw_ipv6.remote_sl
+* The service level used by the source of the received message.
+*
+* recv.raw_ipv6.path_bits
+* path bits...
+*
+* recv.raw_ether.remote_lid
+* The source LID of the received message.
+*
+* recv.raw_ether.remote_sl
+* The service level used by the source of the received message.
+*
+* recv.raw_ether.path_bits
+* path bits...
+*
+* recv.raw_ether.ether_type
+* ether type...
+* NOTES
+* When the work request completes with error, the only values that the
+* consumer can depend on are the wr_id field, and the status of the
+* operation.
+*
+* If the consumer is using the same CQ for completions from more than
+* one type of QP (i.e Reliable Connected, Datagram etc), then the consumer
+* must have additional information to decide what fields of the union are
+* valid.
+* SEE ALSO
+* ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t
+*****/
+
+
+/****s* Access Layer/ib_mr_create_t
+* NAME
+* ib_mr_create_t
+*
+* DESCRIPTION
+* Information required to create a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_create
+{
+ void *vaddr;
+ uint64_t length;
+ ib_access_t access_ctrl;
+
+} ib_mr_create_t;
+/*
+* FIELDS
+* vaddr
+* Starting virtual address of the region being registered.
+*
+* length
+* Length of the buffer to register.
+*
+* access_ctrl
+* Access rights of the registered region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_phys_create_t
+* NAME
+* ib_phys_create_t
+*
+* DESCRIPTION
+* Information required to create a physical memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_create
+{
+ uint64_t length;
+ uint32_t num_bufs;
+ uint64_t *buf_array;
+ uint32_t buf_offset;
+ uint32_t page_size;
+ ib_access_t access_ctrl;
+
+} ib_phys_create_t;
+/*
+* length
+* The length of the memory region in bytes.
+*
+* num_bufs
+* Number of buffers listed in the specified buffer array.
+*
+* buf_array
+* An array of physical buffers to be registered as a single memory
+* region.
+*
+* buf_offset
+* The offset into the first physical page of the specified memory
+* region to start the virtual address.
+*
+* page_size
+* The physical page size of the memory being registered.
+*
+* access_ctrl
+* Access rights of the registered region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_mr_attr_t
+* NAME
+* ib_mr_attr_t
+*
+* DESCRIPTION
+* Attributes of a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_attr
+{
+ ib_pd_handle_t h_pd;
+ void *local_lb;
+ void *local_ub;
+ void *remote_lb;
+ void *remote_ub;
+ ib_access_t access_ctrl;
+ uint32_t lkey;
+ uint32_t rkey;
+
+} ib_mr_attr_t;
+/*
+* DESCRIPTION
+* h_pd
+* Handle to the protection domain for this memory region.
+*
+* local_lb
+* The virtual address of the lower bound of protection for local
+* memory access.
+*
+* local_ub
+* The virtual address of the upper bound of protection for local
+* memory access.
+*
+* remote_lb
+* The virtual address of the lower bound of protection for remote
+* memory access.
+*
+* remote_ub
+* The virtual address of the upper bound of protection for remote
+* memory access.
+*
+* access_ctrl
+* Access rights for the specified memory region.
+*
+* lkey
+* The lkey associated with this memory region.
+*
+* rkey
+* The rkey associated with this memory region.
+*
+* NOTES
+* The remote_lb, remote_ub, and rkey are only valid if remote memory access
+* is enabled for this memory region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****d* Access Layer/ib_ca_mod_t
+* NAME
+* ib_ca_mod_t -- Modify port attributes and error counters
+*
+* DESCRIPTION
+* Specifies modifications to the port attributes of a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_ca_mod_t;
+#define IB_CA_MOD_IS_CM_SUPPORTED 0x00000001
+#define IB_CA_MOD_IS_SNMP_SUPPORTED 0x00000002
+#define IB_CA_MOD_IS_DEV_MGMT_SUPPORTED 0x00000004
+#define IB_CA_MOD_IS_VEND_SUPPORTED 0x00000008
+#define IB_CA_MOD_IS_SM 0x00000010
+#define IB_CA_MOD_IS_SM_DISABLED 0x00000020
+#define IB_CA_MOD_QKEY_CTR 0x00000040
+#define IB_CA_MOD_PKEY_CTR 0x00000080
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED 0x00000100
+#define IB_CA_MOD_IS_TRAP_SUPPORTED 0x00000200
+#define IB_CA_MOD_IS_APM_SUPPORTED 0x00000400
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED 0x00000800
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED 0x00001000
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED 0x00002000
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED 0x00004000
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED 0x00008000
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED 0x00010000
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED 0x00020000
+#define IB_CA_MOD_IS_REINIT_SUPORTED 0x00040000
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED 0x00080000
+#define IB_CA_MOD_SHUTDOWN_PORT 0x00100000
+#define IB_CA_MOD_INIT_TYPE_VALUE 0x00200000
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID 0x00400000
+/*
+* VALUES
+* IB_CA_MOD_IS_CM_SUPPORTED
+* Indicates if there is a communication manager accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SNMP_SUPPORTED
+* Indicates if there is an SNMP agent accessible through the port.
+*
+* IB_CA_MOD_IS_DEV_MGMT_SUPPORTED
+* Indicates if there is a device management agent accessible through
+* the port.
+*
+* IB_CA_MOD_IS_VEND_SUPPORTED
+* Indicates if there is a vendor supported agent accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SM
+* Indicates if there is a subnet manager accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SM_DISABLED
+* Indicates if the port has been disabled for configuration by the subnet
+* manager.
+*
+* IB_CA_MOD_QKEY_CTR
+* Used to reset the qkey violation counter associated with the port.
+*
+* IB_CA_MOD_PKEY_CTR
+* Used to reset the pkey violation counter associated with the port.
+*
+* IB_CA_MOD_IS_NOTICE_SUPPORTED
+* Indicates that this CA supports ability to generate Notices for
+* Port State changes. (only applicable to switches)
+*
+* IB_CA_MOD_IS_TRAP_SUPPORTED
+* Indicates that this management port supports ability to generate
+* trap messages. (only applicable to switches)
+*
+* IB_CA_MOD_IS_APM_SUPPORTED
+* Indicates that this port is capable of performing Automatic Migration.
+*
+* IB_CA_MOD_IS_SLMAP_SUPPORTED
+* Indicates this port supports SLMAP capability.
+*
+* IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED
+* Indicates that PKEY is supported in NVRAM
+*
+* IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED
+* Indicates that MKEY is supported in NVRAM
+*
+* IB_CA_MOD_IS_SYSGUID_SUPPORTED
+* Indicates System Image GUID support.
+*
+* IB_CA_MOD_IS_DR_NOTICE_SUPPORTED
+* Indicate support for generating Direct Routed Notices
+*
+* IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED
+* Indicates support for Boot Management
+*
+* IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED
+* Indicates capability to generate notices for changes to CAPMASK
+*
+* IB_CA_MOD_IS_REINIT_SUPORTED
+* Indicates type of node init supported. Refer to Chapter 14 for
+* Initialization actions.
+*
+* IB_CA_MOD_IS_LEDINFO_SUPPORTED
+* Indicates support for LED info.
+*
+* IB_CA_MOD_SHUTDOWN_PORT
+* Used to modify the port active indicator.
+*
+* IB_CA_MOD_INIT_TYPE_VALUE
+* Used to modify the init_type value for the port.
+*
+* IB_CA_MOD_SYSTEM_IMAGE_GUID
+* Used to modify the system image GUID for the port.
+*****/
+
+
+/****d* Access Layer/ib_mr_mod_t
+* NAME
+* ib_mr_mod_t
+*
+* DESCRIPTION
+* Mask used to specify which attributes of a registered memory region are
+* being modified.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_mr_mod_t;
+#define IB_MR_MOD_ADDR 0x00000001
+#define IB_MR_MOD_PD 0x00000002
+#define IB_MR_MOD_ACCESS 0x00000004
+/*
+* PARAMETERS
+* IB_MEM_MOD_ADDR
+* The address of the memory region is being modified.
+*
+* IB_MEM_MOD_PD
+* The protection domain associated with the memory region is being
+* modified.
+*
+* IB_MEM_MOD_ACCESS
+* The access rights the memory region are being modified.
+*****/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT
+* NAME
+* IB_SMINFO_STATE_INIT
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_INIT 4
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER
+* NAME
+* IB_SMINFO_ATTR_MOD_HANDOVER
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_HANDOVER (CL_NTOH32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+* NAME
+* IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE (CL_NTOH32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE
+* NAME
+* IB_SMINFO_ATTR_MOD_DISABLE
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISABLE (CL_NTOH32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY
+* NAME
+* IB_SMINFO_ATTR_MOD_STANDBY
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_STANDBY (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER
+* NAME
+* IB_SMINFO_ATTR_MOD_DISCOVER
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISCOVER (CL_NTOH32(0x000005))
+/**********/
+
+/****s* Access Layer/ib_ci_op_t
+* NAME
+* ib_ci_op_t
+*
+* DESCRIPTION
+* A structure used for vendor specific CA interface communication.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ci_op
+{
+ IN uint32_t command;
+ IN OUT void* p_buf OPTIONAL;
+ IN uint32_t buf_size;
+ IN OUT uint32_t num_bytes_ret;
+ IN OUT int32_t status;
+
+} ib_ci_op_t;
+/*
+* FIELDS
+* command
+* A command code that is understood by the verbs provider.
+*
+* p_buf
+* A reference to a buffer containing vendor specific data. The verbs
+* provider must not access pointers in the p_buf between user-mode and
+* kernel-mode. Any pointers embedded in the p_buf are invalidated by
+* the user-mode/kernel-mode transition.
+*
+* buf_size
+* The size of the buffer in bytes.
+*
+* num_bytes_ret
+* The size in bytes of the vendor specific data returned in the buffer.
+* This field is set by the verbs provider. The verbs provider should
+* verify that the buffer size is sufficient to hold the data being
+* returned.
+*
+* status
+* The completion status from the verbs provider. This field should be
+* initialize to indicate an error to allow detection and cleanup in
+* case a communication error occurs between user-mode and kernel-mode.
+*
+* NOTES
+* This structure is provided to allow the exchange of vendor specific
+* data between the originator and the verbs provider. Users of this
+* structure are expected to know the format of data in the p_buf based
+* on the structure command field or the usage context.
+*****/
+
+END_C_DECLS
+
+#endif
+#if defined( __WIN__ )
+ #include <iba/ib_types_extended.h>
+#endif
+
+#endif // __IB_TYPES_H__
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#if !defined(__IB_TYPES_EXTENDED_H__)
+#define __IB_TYPES_EXTENDED_H__
+
+
+#if defined( WIN32 )
+ #if defined( EXPORT_AL_SYMBOLS )
+ #define AL_EXPORT __declspec(dllexport)
+ #else
+ #define AL_EXPORT __declspec(dllimport)
+ #endif
+
+ #ifdef CL_KERNEL
+ #define AL_API
+ #define AL_INLINE static inline
+ #else
+ #define AL_API __stdcall
+ #define AL_INLINE AL_EXPORT inline
+ #endif /* CL_KERNEL */
+#else
+ #define AL_EXPORT extern
+ #define AL_INLINE static inline
+ #define AL_API
+ #define __ptr64
+#endif
+/*
+ * Defines the size of user available data in communication management MADs
+ */
+#define IB_REQ_PDATA_SIZE 92
+#define IB_MRA_PDATA_SIZE 222
+#define IB_REJ_PDATA_SIZE 148
+#define IB_REP_PDATA_SIZE 196
+#define IB_RTU_PDATA_SIZE 224
+#define IB_LAP_PDATA_SIZE 168
+#define IB_APR_PDATA_SIZE 148
+#define IB_DREQ_PDATA_SIZE 220
+#define IB_DREP_PDATA_SIZE 224
+#define IB_SIDR_REQ_PDATA_SIZE 216
+#define IB_SIDR_REP_PDATA_SIZE 136
+
+/* following v1 ver1.2 p901 */
+#define IB_PATH_RECORD_RATE_5_GBS 5
+#define IB_PATH_RECORD_RATE_20_GBS 6
+#define IB_PATH_RECORD_RATE_40_GBS 7
+#define IB_PATH_RECORD_RATE_60_GBS 8
+#define IB_PATH_RECORD_RATE_80_GBS 9
+#define IB_PATH_RECORD_RATE_120_GBS 10
+
+
+
+/*
+ * The following definitions are shared between the Access Layer and VPD
+ */
+
+
+
+/****d* Access Layer/ib_api_status_t
+* NAME
+* ib_api_status_t
+*
+* DESCRIPTION
+* Function return codes indicating the success or failure of an API call.
+* Note that success is indicated by the return value IB_SUCCESS, which
+* is always zero.
+*
+* NOTES
+* IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call
+* in the pre-ioctl step itself.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_api_status_t
+{
+ IB_SUCCESS,
+ IB_INSUFFICIENT_RESOURCES,
+ IB_INSUFFICIENT_MEMORY,
+ IB_INVALID_PARAMETER,
+ IB_INVALID_SETTING,
+ IB_NOT_FOUND,
+ IB_TIMEOUT,
+ IB_CANCELED,
+ IB_INTERRUPTED,
+ IB_INVALID_PERMISSION,
+ IB_UNSUPPORTED,
+ IB_OVERFLOW,
+ IB_MAX_MCAST_QPS_REACHED,
+ IB_INVALID_QP_STATE,
+ IB_INVALID_APM_STATE,
+ IB_INVALID_PORT_STATE,
+ IB_INVALID_STATE,
+ IB_RESOURCE_BUSY,
+ IB_INVALID_PKEY,
+ IB_INVALID_LKEY,
+ IB_INVALID_RKEY,
+ IB_INVALID_MAX_WRS,
+ IB_INVALID_MAX_SGE,
+ IB_INVALID_CQ_SIZE,
+ IB_INVALID_SERVICE_TYPE,
+ IB_INVALID_GID,
+ IB_INVALID_LID,
+ IB_INVALID_GUID,
+ IB_INVALID_CA_HANDLE,
+ IB_INVALID_AV_HANDLE,
+ IB_INVALID_CQ_HANDLE,
+ IB_INVALID_QP_HANDLE,
+ IB_INVALID_PD_HANDLE,
+ IB_INVALID_MR_HANDLE,
+ IB_INVALID_MW_HANDLE,
+ IB_INVALID_MCAST_HANDLE,
+ IB_INVALID_CALLBACK,
+ IB_INVALID_AL_HANDLE, /* InfiniBand Access Layer */
+ IB_INVALID_HANDLE, /* InfiniBand Access Layer */
+ IB_ERROR, /* InfiniBand Access Layer */
+ IB_REMOTE_ERROR, /* Infiniband Access Layer */
+ IB_VERBS_PROCESSING_DONE, /* See Notes above */
+ IB_INVALID_WR_TYPE,
+ IB_QP_IN_TIMEWAIT,
+ IB_INVALID_PORT,
+ IB_NOT_DONE,
+ IB_INVALID_INDEX,
+ IB_NO_MATCH,
+ IB_PENDING,
+ IB_UNKNOWN_ERROR /* ALWAYS LAST ENUM VALUE! */
+
+} ib_api_status_t;
+/*****/
+
+
+
+/****f* IBA Base: Types/ib_get_err_str
+* NAME
+* ib_get_err_str
+*
+* DESCRIPTION
+* Returns a string for the specified status value.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_err_str(
+ IN ib_api_status_t status );
+/*
+* PARAMETERS
+* status
+* [in] status value
+*
+* RETURN VALUES
+* Pointer to the status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* Verbs/ib_async_event_t
+* NAME
+* ib_async_event_t -- Async event types
+*
+* DESCRIPTION
+* This type indicates the reason the async callback was called.
+* The context in the ib_event_rec_t indicates the resource context
+* that associated with the callback. For example, for IB_AE_CQ_ERROR
+* the context provided during the ib_create_cq is returned in the event.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_async_event_t
+{
+ IB_AE_SQ_ERROR = 1,
+ IB_AE_SQ_DRAINED,
+ IB_AE_RQ_ERROR,
+ IB_AE_CQ_ERROR,
+ IB_AE_QP_FATAL,
+ IB_AE_QP_COMM,
+ IB_AE_QP_APM,
+ IB_AE_LOCAL_FATAL,
+ IB_AE_PKEY_TRAP,
+ IB_AE_QKEY_TRAP,
+ IB_AE_MKEY_TRAP,
+ IB_AE_PORT_TRAP,
+ IB_AE_SYSIMG_GUID_TRAP,
+ IB_AE_BUF_OVERRUN,
+ IB_AE_LINK_INTEGRITY,
+ IB_AE_FLOW_CTRL_ERROR,
+ IB_AE_BKEY_TRAP,
+ IB_AE_QP_APM_ERROR,
+ IB_AE_WQ_REQ_ERROR,
+ IB_AE_WQ_ACCESS_ERROR,
+ IB_AE_PORT_ACTIVE,
+ IB_AE_PORT_DOWN,
+ IB_AE_UNKNOWN /* ALWAYS LAST ENUM VALUE */
+
+} ib_async_event_t;
+/*
+* VALUES
+* IB_AE_SQ_ERROR
+* An error occurred when accessing the send queue of the QP.
+* This event is optional.
+*
+* IB_AE_SQ_DRAINED
+* The send queue of the specified QP has completed the outstanding
+* messages in progress when the state change was requested and, if
+* applicable, has received all acknowledgements for those messages.
+*
+* IB_AE_RQ_ERROR
+* An error occurred when accessing the receive queue of the QP.
+* This event is optional.
+*
+* IB_AE_CQ_ERROR
+* An error occurred when writing an entry to the CQ.
+*
+* IB_AE_QP_FATAL
+* A catastrophic error occurred while accessing or processing the
+* work queue that prevents reporting of completions.
+*
+* IB_AE_QP_COMM
+* The first packet has arrived for the receive work queue where the
+* QP is still in the RTR state.
+*
+* IB_AE_QP_APM
+* If alternate path migration is supported, this event indicates that
+* the QP connection has migrated to the alternate path.
+*
+* IB_AE_LOCAL_FATAL
+* A catastrophic HCA error occurred which cannot be attributed to any
+* resource; behavior is indeterminate.
+*
+* IB_AE_PKEY_TRAP
+* A PKEY violation was detected. This event is optional.
+*
+* IB_AE_QKEY_TRAP
+* A QKEY violation was detected. This event is optional.
+*
+* IB_AE_MKEY_TRAP
+* An MKEY violation was detected. This event is optional.
+*
+* IB_AE_PORT_TRAP
+* A port capability change was detected. This event is optional.
+*
+* IB_AE_SYSIMG_GUID_TRAP
+* If the system image GUID is supported, this event indicates that the
+* system image GUID of this HCA has been changed. This event is
+* optional.
+*
+* IB_AE_BUF_OVERRUN
+* The number of consecutive flow control update periods with at least
+* one overrun error in each period has exceeded the threshold specified
+* in the port info attributes. This event is optional.
+*
+* IB_AE_LINK_INTEGRITY
+* The detection of excessively frequent local physical errors has
+* exceeded the threshold specified in the port info attributes. This
+* event is optional.
+*
+* IB_AE_FLOW_CTRL_ERROR
+* An HCA watchdog timer monitoring the arrival of flow control updates
+* has expired without receiving an update. This event is optional.
+*
+* IB_AE_BKEY_TRAP
+* An BKEY violation was detected. This event is optional.
+*
+* IB_AE_QP_APM_ERROR
+* If alternate path migration is supported, this event indicates that
+* an incoming path migration request to this QP was not accepted.
+*
+* IB_AE_WQ_REQ_ERROR
+* An OpCode violation was detected at the responder.
+*
+* IB_AE_WQ_ACCESS_ERROR
+* An access violation was detected at the responder.
+*
+* IB_AE_PORT_ACTIVE
+* If the port active event is supported, this event is generated
+* when the link becomes active: IB_LINK_ACTIVE.
+*
+* IB_AE_PORT_DOWN
+* The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,
+* IB_LINK_DOWN.
+*
+* IB_AE_UNKNOWN
+* An unknown error occurred which cannot be attributed to any
+* resource; behavior is indeterminate.
+*
+*****/
+
+
+
+/****f* IBA Base: Types/ib_get_async_event_str
+* NAME
+* ib_get_async_event_str
+*
+* DESCRIPTION
+* Returns a string for the specified asynchronous event.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_async_event_str(
+ IN ib_async_event_t event );
+/*
+* PARAMETERS
+* event
+* [in] event value
+*
+* RETURN VALUES
+* Pointer to the asynchronous event description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****s* Verbs/ib_event_rec_t
+* NAME
+* ib_event_rec_t -- Async event notification record
+*
+* DESCRIPTION
+* When an async event callback is made, this structure is passed to indicate
+* the type of event, the source of event that caused it, and the context
+* associated with this event.
+*
+* context -- Context of the resource that caused the event.
+* -- ca_context if this is a port/adapter event.
+* -- qp_context if the source is a QP event
+* -- cq_context if the source is a CQ event.
+* -- ee_context if the source is an EE event.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_event_rec
+{
+ void* __ptr64 context;
+ ib_async_event_t type;
+
+ /* HCA vendor specific event information. */
+ uint64_t vendor_specific;
+
+ /* The following structures are valid only for trap types. */
+ union _trap
+ {
+ struct
+ {
+ uint16_t lid;
+ ib_net64_t port_guid;
+ uint8_t port_num;
+
+ /*
+ * The following structure is valid only for
+ * P_KEY, Q_KEY, and M_KEY violation traps.
+ */
+ struct
+ {
+ uint8_t sl;
+ uint16_t src_lid;
+ uint16_t dest_lid;
+ union _key
+ {
+ uint16_t pkey;
+ uint32_t qkey;
+ uint64_t mkey;
+ } key;
+ uint32_t src_qp;
+ uint32_t dest_qp;
+ ib_gid_t src_gid;
+ ib_gid_t dest_gid;
+
+ } violation;
+
+ } info;
+
+ ib_net64_t sysimg_guid;
+
+ } trap;
+
+} ib_event_rec_t;
+/*******/
+
+
+/****d* Access Layer/ib_atomic_t
+* NAME
+* ib_atomic_t
+*
+* DESCRIPTION
+* Indicates atomicity levels supported by an adapter.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_atomic_t
+{
+ IB_ATOMIC_NONE,
+ IB_ATOMIC_LOCAL,
+ IB_ATOMIC_GLOBAL
+
+} ib_atomic_t;
+/*
+* VALUES
+* IB_ATOMIC_NONE
+* Atomic operations not supported.
+*
+* IB_ATOMIC_LOCAL
+* Atomic operations guaranteed between QPs of a single CA.
+*
+* IB_ATOMIC_GLOBAL
+* Atomic operations are guaranteed between CA and any other entity
+* in the system.
+*****/
+
+
+/****s* Access Layer/ib_port_cap_t
+* NAME
+* ib_port_cap_t
+*
+* DESCRIPTION
+* Indicates which management agents are currently available on the specified
+* port.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_cap
+{
+ boolean_t cm;
+ boolean_t snmp;
+ boolean_t dev_mgmt;
+ boolean_t vend;
+ boolean_t sm;
+ boolean_t sm_disable;
+ boolean_t qkey_ctr;
+ boolean_t pkey_ctr;
+ boolean_t notice;
+ boolean_t trap;
+ boolean_t apm;
+ boolean_t slmap;
+ boolean_t pkey_nvram;
+ boolean_t mkey_nvram;
+ boolean_t sysguid;
+ boolean_t dr_notice;
+ boolean_t boot_mgmt;
+ boolean_t capm_notice;
+ boolean_t reinit;
+ boolean_t ledinfo;
+ boolean_t port_active;
+ boolean_t ipd;
+ boolean_t pkey_switch_ext_port;
+ boolean_t bm;
+ boolean_t link_rtl;
+ boolean_t client_reregister;
+
+} ib_port_cap_t;
+/*****/
+
+
+/****d* Access Layer/ib_init_type_t
+* NAME
+* ib_init_type_t
+*
+* DESCRIPTION
+* If supported by the HCA, the type of initialization requested by
+* this port before SM moves it to the active or armed state. If the
+* SM implements reinitialization, it shall set these bits to indicate
+* the type of initialization performed prior to activating the port.
+* Otherwise, these bits shall be set to 0.
+*
+* SYNOPSIS
+*/
+typedef uint8_t ib_init_type_t;
+#define IB_INIT_TYPE_NO_LOAD 0x01
+#define IB_INIT_TYPE_PRESERVE_CONTENT 0x02
+#define IB_INIT_TYPE_PRESERVE_PRESENCE 0x04
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE 0x08
+/*****/
+
+
+/****s* Access Layer/ib_port_attr_mod_t
+* NAME
+* ib_port_attr_mod_t
+*
+* DESCRIPTION
+* Port attributes that may be modified.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr_mod
+{
+ ib_port_cap_t cap;
+ uint16_t pkey_ctr;
+ uint16_t qkey_ctr;
+
+ ib_init_type_t init_type;
+ ib_net64_t system_image_guid;
+
+} ib_port_attr_mod_t;
+/*
+* SEE ALSO
+* ib_port_cap_t
+*****/
+
+
+/****s* Access Layer/ib_port_attr_t
+* NAME
+* ib_port_attr_t
+*
+* DESCRIPTION
+* Information about a port on a given channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr
+{
+ ib_net64_t port_guid;
+ uint8_t port_num;
+ uint8_t mtu;
+ uint64_t max_msg_size;
+ ib_net16_t lid;
+ uint8_t lmc;
+
+ /*
+ * LinkWidthSupported as defined in PortInfo. Required to calculate
+ * inter-packet delay (a.k.a. static rate).
+ */
+ uint8_t link_width_supported;
+
+ uint16_t max_vls;
+
+ ib_net16_t sm_lid;
+ uint8_t sm_sl;
+ uint8_t link_state;
+
+ ib_init_type_t init_type_reply; /* Optional */
+
+ /*
+ * subnet_timeout:
+ * The maximum expected subnet propagation delay to reach any port on
+ * the subnet. This value also determines the rate at which traps can
+ * be generated from this node.
+ *
+ * timeout = 4.096 microseconds * 2^subnet_timeout
+ */
+ uint8_t subnet_timeout;
+
+ ib_port_cap_t cap;
+ uint16_t pkey_ctr;
+ uint16_t qkey_ctr;
+
+ uint16_t num_gids;
+ uint16_t num_pkeys;
+ /*
+ * Pointers at the end of the structure to allow doing a simple
+ * memory comparison of contents up to the first pointer.
+ */
+ ib_gid_t* __ptr64 p_gid_table;
+ ib_net16_t* __ptr64 p_pkey_table;
+
+} ib_port_attr_t;
+/*
+* SEE ALSO
+* uint8_t, ib_port_cap_t, ib_link_states_t
+*****/
+
+
+/****s* Access Layer/ib_ca_attr_t
+* NAME
+* ib_ca_attr_t
+*
+* DESCRIPTION
+* Information about a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_attr
+{
+ ib_net64_t ca_guid;
+
+ uint32_t vend_id;
+ uint16_t dev_id;
+ uint16_t revision;
+
+ /*
+ * Total size of the ca attributes in bytes
+ */
+ uint32_t size;
+ uint32_t max_qps;
+ uint32_t max_wrs;
+
+ uint32_t max_sges;
+ uint32_t max_rd_sges;
+
+ uint32_t max_cqs;
+ uint32_t max_cqes;
+
+ uint32_t max_pds;
+
+ uint32_t init_regions;
+ uint64_t init_region_size;
+
+ uint32_t init_windows;
+ uint32_t max_addr_handles;
+
+ uint32_t max_partitions;
+
+ ib_atomic_t atomicity;
+
+ uint8_t max_qp_resp_res;
+ uint8_t max_resp_res;
+
+ uint8_t max_qp_init_depth;
+
+ uint32_t max_ipv6_qps;
+ uint32_t max_ether_qps;
+
+ uint32_t max_mcast_grps;
+ uint32_t max_mcast_qps;
+ uint32_t max_qps_per_mcast_grp;
+
+ /*
+ * local_ack_delay:
+ * Specifies the maximum time interval between the local CA receiving
+ * a message and the transmission of the associated ACK or NAK.
+ *
+ * timeout = 4.096 microseconds * 2^local_ack_delay
+ */
+ uint8_t local_ack_delay;
+
+ boolean_t bad_pkey_ctr_support;
+ boolean_t bad_qkey_ctr_support;
+ boolean_t raw_mcast_support;
+ boolean_t apm_support;
+ boolean_t av_port_check;
+ boolean_t change_primary_port;
+ boolean_t modify_wr_depth;
+ boolean_t current_qp_state_support;
+ boolean_t shutdown_port_capability;
+ boolean_t init_type_support;
+ boolean_t port_active_event_support;
+ boolean_t system_image_guid_support;
+ boolean_t hw_agents;
+
+ ib_net64_t system_image_guid;
+
+ uint32_t num_page_sizes;
+ uint8_t num_ports;
+
+ uint32_t* __ptr64 p_page_size;
+ ib_port_attr_t* __ptr64 p_port_attr;
+
+} ib_ca_attr_t;
+/*
+* FIELDS
+* ca_guid
+* GUID for this adapter.
+*
+* vend_id
+* IEEE vendor ID for this adapter
+*
+* dev_id
+* Device ID of this adapter. (typically from PCI device ID)
+*
+* revision
+* Revision ID of this adapter
+*
+* size
+* Total size in bytes for the HCA attributes. This size includes total
+* size required for all the variable members of the structure. If a
+* vendor requires to pass vendor specific fields beyond this structure,
+* the HCA vendor can choose to report a larger size. If a vendor is
+* reporting extended vendor specific features, they should also provide
+* appropriate access functions to aid with the required interpretation.
+*
+* max_qps
+* Maximum number of QP's supported by this HCA.
+*
+* max_wrs
+* Maximum number of work requests supported by this HCA.
+*
+* max_sges
+* Maximum number of scatter gather elements supported per work request.
+*
+* max_rd_sges
+* Maximum number of scatter gather elements supported for READ work
+* requests for a Reliable Datagram QP. This value must be zero if RD
+* service is not supported.
+*
+* max_cqs
+* Maximum number of Completion Queues supported.
+*
+* max_cqes
+* Maximum number of CQ elements supported per CQ.
+*
+* max_pds
+* Maximum number of protection domains supported.
+*
+* init_regions
+* Initial number of memory regions supported. These are only informative
+* values. HCA vendors can extended and grow these limits on demand.
+*
+* init_region_size
+* Initial limit on the size of the registered memory region.
+*
+* init_windows
+* Initial number of window entries supported.
+*
+* max_addr_handles
+* Maximum number of address handles supported.
+*
+* max_partitions
+* Maximum number of partitions supported.
+*
+* atomicity
+* Indicates level of atomic operations supported by this HCA.
+*
+* max_qp_resp_res
+* Maximum limit on number of responder resources for incomming RDMA
+* operations on QPs.
+*
+* max_resp_res
+* Maximum number of responder resources per HCA, with this HCA used as
+* the target.
+*
+* max_qp_init_depth
+* Maximimum initiator depth per QP for initiating RDMA reads and
+* atomic operations.
+*
+* max_ipv6_qps
+* max_ether_qps
+* Maximum number of IPV6 and raw ether QP's supported by this HCA.
+*
+* max_mcast_grps
+* Maximum number of multicast groups supported.
+*
+* max_mcast_qps
+* Maximum number of QP's that can support multicast operations.
+*
+* max_qps_per_mcast_grp
+* Maximum number of multicast QP's per multicast group.
+*
+* local_ack_delay
+* Specifies the maximum time interval between the local CA receiving
+* a message and the transmission of the associated ACK or NAK.
+* timeout = 4.096 microseconds * 2^local_ack_delay
+*
+* bad_pkey_ctr_support
+* bad_qkey_ctr_support
+* Indicates support for the bad pkey and qkey counters.
+*
+* raw_mcast_support
+* Indicates support for raw packet multicast.
+*
+* apm_support
+* Indicates support for Automatic Path Migration.
+*
+* av_port_check
+* Indicates ability to check port number in address handles.
+*
+* change_primary_port
+* Indicates ability to change primary port for a QP during a
+* SQD->RTS transition.
+*
+* modify_wr_depth
+* Indicates ability to modify QP depth during a modify QP operation.
+* Check the verb specification for permitted states.
+*
+* current_qp_state_support
+* Indicates ability of the HCA to support the current QP state modifier
+* during a modify QP operation.
+*
+* shutdown_port_capability
+* Shutdown port capability support indicator.
+*
+* init_type_support
+* Indicates init_type_reply and ability to set init_type is supported.
+*
+* port_active_event_support
+* Port active event support indicator.
+*
+* system_image_guid_support
+* System image GUID support indicator.
+*
+* hw_agents
+* Indicates SMA is implemented in HW.
+*
+* system_image_guid
+* Optional system image GUID. This field is valid only if the
+* system_image_guid_support flag is set.
+*
+* num_page_sizes
+* Indicates support for different page sizes supported by the HCA.
+* The variable size array can be obtained from p_page_size.
+*
+* num_ports
+* Number of physical ports supported on this HCA.
+*
+* p_page_size
+* Array holding different page size supported.
+*
+* p_port_attr
+* Array holding port attributes.
+*
+* NOTES
+* This structure contains the attributes of a channel adapter. Users must
+* call ib_copy_ca_attr to copy the contents of this structure to a new
+* memory region.
+*
+* SEE ALSO
+* ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr
+*****/
+
+/****f* Access layer/ib_copy_ca_attr
+* NAME
+* ib_copy_ca_attr
+*
+* DESCRIPTION
+* Copies CA attributes.
+*
+* SYNOPSIS
+*/
+AL_EXPORT ib_ca_attr_t* AL_API
+ib_copy_ca_attr(
+ IN ib_ca_attr_t* const p_dest,
+ IN const ib_ca_attr_t* const p_src );
+/*
+* PARAMETERS
+* p_dest
+* Pointer to the buffer that is the destination of the copy.
+*
+* p_src
+* Pointer to the CA attributes to copy.
+*
+* RETURN VALUE
+* Pointer to the copied CA attributes.
+*
+* NOTES
+* The buffer pointed to by the p_dest parameter must be at least the size
+* specified in the size field of the buffer pointed to by p_src.
+*
+* SEE ALSO
+* ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr
+*****/
+
+
+/****d* Access Layer/ib_pd_type_t
+* NAME
+* ib_pd_type_t
+*
+* DESCRIPTION
+* Indicates the type of protection domain being allocated.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_pd_type
+{
+ IB_PDT_NORMAL,
+ IB_PDT_ALIAS,
+ IB_PDT_SQP
+
+} ib_pd_type_t;
+/*
+* VALUES
+* IB_PDT_NORMAL
+* Protection domain for all non-aliased QPs.
+*
+* IB_PDT_ALIAS
+* Protection domain for IB_QPT_QP0_ALIAS and IB_QPT_QP1_ALIAS QPs.
+*
+* IB_PDT_SQP
+* Protection domain for special queue pair usage.
+*****/
+
+
+/****s* Access Layer/ib_av_attr_t
+* NAME
+* ib_av_attr_t
+*
+* DESCRIPTION
+* IBA address vector.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_av_attr
+{
+ uint8_t port_num;
+
+ uint8_t sl;
+ ib_net16_t dlid;
+
+ boolean_t grh_valid;
+ ib_grh_t grh;
+ uint8_t static_rate;
+ uint8_t path_bits;
+
+ struct _av_conn
+ {
+ uint8_t path_mtu;
+ uint8_t local_ack_timeout;
+ uint8_t seq_err_retry_cnt;
+ uint8_t rnr_retry_cnt;
+
+ } conn;
+
+} ib_av_attr_t;
+/*
+* SEE ALSO
+* ib_gid_t
+*****/
+
+
+/****d* Access Layer/ib_qp_type_t
+* NAME
+* ib_qp_type_t
+*
+* DESCRIPTION
+* Indicates the type of queue pair being created.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_qp_type
+{
+ IB_QPT_RELIABLE_CONN = 0, /* Matches CM REQ transport type */
+ IB_QPT_UNRELIABLE_CONN = 1, /* Matches CM REQ transport type */
+ IB_QPT_UNRELIABLE_DGRM = 3, /* Purposefully skip RDD type. */
+ IB_QPT_QP0,
+ IB_QPT_QP1,
+ IB_QPT_RAW_IPV6,
+ IB_QPT_RAW_ETHER,
+ IB_QPT_MAD, /* InfiniBand Access Layer */
+ IB_QPT_QP0_ALIAS, /* InfiniBand Access Layer */
+ IB_QPT_QP1_ALIAS /* InfiniBand Access Layer */
+
+} ib_qp_type_t;
+/*
+* VALUES
+* IB_QPT_RELIABLE_CONN
+* Reliable, connected queue pair.
+*
+* IB_QPT_UNRELIABLE_CONN
+* Unreliable, connected queue pair.
+*
+* IB_QPT_UNRELIABLE_DGRM
+* Unreliable, datagram queue pair.
+*
+* IB_QPT_QP0
+* Queue pair 0.
+*
+* IB_QPT_QP1
+* Queue pair 1.
+*
+* IB_QPT_RAW_DGRM
+* Raw datagram queue pair.
+*
+* IB_QPT_RAW_IPV6
+* Raw IP version 6 queue pair.
+*
+* IB_QPT_RAW_ETHER
+* Raw Ethernet queue pair.
+*
+* IB_QPT_MAD
+* Unreliable, datagram queue pair that will send and receive management
+* datagrams with assistance from the access layer.
+*
+* IB_QPT_QP0_ALIAS
+* Alias to queue pair 0. Aliased QPs can only be created on an aliased
+* protection domain.
+*
+* IB_QPT_QP1_ALIAS
+* Alias to queue pair 1. Aliased QPs can only be created on an aliased
+* protection domain.
+*****/
+
+
+/****d* Access Layer/ib_access_t
+* NAME
+* ib_access_t
+*
+* DESCRIPTION
+* Indicates the type of access is permitted on resources such as QPs,
+* memory regions and memory windows.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_access_t;
+#define IB_AC_RDMA_READ 0x00000001
+#define IB_AC_RDMA_WRITE 0x00000002
+#define IB_AC_ATOMIC 0x00000004
+#define IB_AC_LOCAL_WRITE 0x00000008
+#define IB_AC_MW_BIND 0x00000010
+/*
+* NOTES
+* Users may combine access rights using a bit-wise or operation to specify
+* additional access. For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants
+* RDMA read and write access.
+*****/
+
+
+/****d* Access Layer/ib_qp_state_t
+* NAME
+* ib_qp_state_t
+*
+* DESCRIPTION
+* Indicates or sets the state of a queue pair. The current state of a queue
+* pair is returned through the ib_qp_query call and set via the
+* ib_qp_modify call.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_state_t;
+#define IB_QPS_RESET 0x00000001
+#define IB_QPS_INIT 0x00000002
+#define IB_QPS_RTR 0x00000004
+#define IB_QPS_RTS 0x00000008
+#define IB_QPS_SQD 0x00000010
+#define IB_QPS_SQD_DRAINING 0x00000030
+#define IB_QPS_SQD_DRAINED 0x00000050
+#define IB_QPS_SQERR 0x00000080
+#define IB_QPS_ERROR 0x00000100
+#define IB_QPS_TIME_WAIT 0xDEAD0000 /* InfiniBand Access Layer */
+/*****/
+
+
+/****d* Access Layer/ib_apm_state_t
+* NAME
+* ib_apm_state_t
+*
+* DESCRIPTION
+* The current automatic path migration state of a queue pair
+*
+* SYNOPSIS
+*/
+typedef enum _ib_apm_state
+{
+ IB_APM_MIGRATED = 1,
+ IB_APM_REARM,
+ IB_APM_ARMED
+
+} ib_apm_state_t;
+/*****/
+
+
+/****s* Access Layer/ib_qp_create_t
+* NAME
+* ib_qp_create_t
+*
+* DESCRIPTION
+* Attributes used to initialize a queue pair at creation time.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_create
+{
+ ib_qp_type_t qp_type;
+
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+ uint32_t sq_sge;
+ uint32_t rq_sge;
+
+ ib_cq_handle_t h_sq_cq;
+ ib_cq_handle_t h_rq_cq;
+
+ boolean_t sq_signaled;
+
+} ib_qp_create_t;
+/*
+* FIELDS
+* type
+* Specifies the type of queue pair to create.
+*
+* sq_depth
+* Indicates the requested maximum number of work requests that may be
+* outstanding on the queue pair's send queue. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* rq_depth
+* Indicates the requested maximum number of work requests that may be
+* outstanding on the queue pair's receive queue. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* sq_sge
+* Indicates the maximum number scatter-gather elements that may be
+* given in a send work request. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* rq_sge
+* Indicates the maximum number scatter-gather elements that may be
+* given in a receive work request. This value must be less
+* than or equal to the maximum reported by the channel adapter associated
+* with the queue pair.
+*
+* h_sq_cq
+* A handle to the completion queue that will be used to report send work
+* request completions. This handle must be NULL if the type is
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+* h_rq_cq
+* A handle to the completion queue that will be used to report receive
+* work request completions. This handle must be NULL if the type is
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+* sq_signaled
+* A flag that is used to indicate whether the queue pair will signal
+* an event upon completion of a send work request. If set to
+* TRUE, send work requests will always generate a completion
+* event. If set to FALSE, a completion event will only be
+* generated if the send_opt field of the send work request has the
+* IB_SEND_OPT_SIGNALED flag set.
+*
+* SEE ALSO
+* ib_qp_type_t, ib_qp_attr_t
+*****/
+
+
+/****s* Access Layer/ib_qp_attr_t
+* NAME
+* ib_qp_attr_t
+*
+* DESCRIPTION
+* Queue pair attributes returned through ib_query_qp.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_attr
+{
+ ib_pd_handle_t h_pd;
+ ib_qp_type_t qp_type;
+ ib_access_t access_ctrl;
+ uint16_t pkey_index;
+
+ uint32_t sq_max_inline;
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+ uint32_t sq_sge;
+ uint32_t rq_sge;
+ uint8_t init_depth;
+ uint8_t resp_res;
+
+ ib_cq_handle_t h_sq_cq;
+ ib_cq_handle_t h_rq_cq;
+
+ boolean_t sq_signaled;
+
+ ib_qp_state_t state;
+ ib_net32_t num;
+ ib_net32_t dest_num;
+ ib_net32_t qkey;
+
+ ib_net32_t sq_psn;
+ ib_net32_t rq_psn;
+
+ uint8_t primary_port;
+ uint8_t alternate_port;
+ ib_av_attr_t primary_av;
+ ib_av_attr_t alternate_av;
+ ib_apm_state_t apm_state;
+
+} ib_qp_attr_t;
+/*
+* FIELDS
+* h_pd
+* This is a handle to a protection domain associated with the QP.
+*
+* sq_max_inline
+* Maximum payload that can be inlined directly in a WQE, eliminating
+* protection checks and additional DMA operations.
+*
+* NOTES
+* Other fields are defined by the Infiniband specification.
+*
+* SEE ALSO
+* ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_qp_opts_t
+* NAME
+* ib_qp_opts_t
+*
+* DESCRIPTION
+* Optional fields supplied in the modify QP operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_opts_t;
+#define IB_MOD_QP_ALTERNATE_AV 0x00000001
+#define IB_MOD_QP_PKEY 0x00000002
+#define IB_MOD_QP_APM_STATE 0x00000004
+#define IB_MOD_QP_PRIMARY_AV 0x00000008
+#define IB_MOD_QP_RNR_NAK_TIMEOUT 0x00000010
+#define IB_MOD_QP_RESP_RES 0x00000020
+#define IB_MOD_QP_INIT_DEPTH 0x00000040
+#define IB_MOD_QP_PRIMARY_PORT 0x00000080
+#define IB_MOD_QP_ACCESS_CTRL 0x00000100
+#define IB_MOD_QP_QKEY 0x00000200
+#define IB_MOD_QP_SQ_DEPTH 0x00000400
+#define IB_MOD_QP_RQ_DEPTH 0x00000800
+#define IB_MOD_QP_CURRENT_STATE 0x00001000
+#define IB_MOD_QP_RETRY_CNT 0x00002000
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT 0x00004000
+#define IB_MOD_QP_RNR_RETRY_CNT 0x00008000
+
+/*
+* SEE ALSO
+* ib_qp_mod_t
+*****/
+
+
+/****s* Access Layer/ib_qp_mod_t
+* NAME
+* ib_qp_mod_t
+*
+* DESCRIPTION
+* Information needed to change the state of a queue pair through the
+* ib_modify_qp call.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_mod
+{
+ ib_qp_state_t req_state;
+
+ union _qp_state
+ {
+ struct _qp_init
+ {
+ ib_qp_opts_t opts;
+ uint8_t primary_port;
+ ib_net32_t qkey;
+ uint16_t pkey_index;
+ ib_access_t access_ctrl;
+
+ } init;
+
+ struct _qp_rtr
+ {
+ ib_net32_t rq_psn;
+ ib_net32_t dest_qp;
+ ib_av_attr_t primary_av;
+ uint8_t resp_res;
+ uint8_t rnr_nak_timeout;
+
+ ib_qp_opts_t opts;
+ ib_av_attr_t alternate_av;
+ ib_net32_t qkey;
+ uint16_t pkey_index;
+ ib_access_t access_ctrl;
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+
+ } rtr;
+
+ struct _qp_rts
+ {
+ ib_net32_t sq_psn;
+ uint8_t retry_cnt;
+ uint8_t rnr_retry_cnt;
+ uint8_t local_ack_timeout;
+ uint8_t init_depth;
+
+ ib_qp_opts_t opts;
+ uint8_t rnr_nak_timeout;
+ ib_qp_state_t current_state;
+ ib_net32_t qkey;
+ ib_access_t access_ctrl;
+ uint8_t resp_res;
+
+ ib_av_attr_t primary_av;
+ ib_av_attr_t alternate_av;
+
+ uint32_t sq_depth;
+ uint32_t rq_depth;
+
+ ib_apm_state_t apm_state;
+ uint8_t primary_port;
+ uint16_t pkey_index;
+
+ } rts;
+
+ struct _qp_sqd
+ {
+ boolean_t sqd_event;
+
+ } sqd;
+
+ } state;
+
+} ib_qp_mod_t;
+/*
+* SEE ALSO
+* ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_wr_type_t
+* NAME
+* ib_wr_type_t
+*
+* DESCRIPTION
+* Identifies the type of work request posted to a queue pair.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wr_type_t
+{
+ WR_SEND = 1,
+ WR_RDMA_WRITE,
+ WR_RDMA_READ,
+ WR_COMPARE_SWAP,
+ WR_FETCH_ADD
+
+} ib_wr_type_t;
+/*****/
+
+
+/****s* Access Layer/ib_local_ds_t
+* NAME
+* ib_local_ds_t
+*
+* DESCRIPTION
+* Local data segment information referenced by send and receive work
+* requests. This is used to specify local data buffers used as part of a
+* work request.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_local_ds
+{
+ uint64_t vaddr;
+ uint32_t length;
+ uint32_t lkey;
+
+} ib_local_ds_t;
+/*****/
+
+
+/****d* Access Layer/ib_send_opt_t
+* NAME
+* ib_send_opt_t
+*
+* DESCRIPTION
+* Optional flags used when posting send work requests. These flags
+* indicate specific processing for the send operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_send_opt_t;
+#define IB_SEND_OPT_IMMEDIATE 0x00000001
+#define IB_SEND_OPT_FENCE 0x00000002
+#define IB_SEND_OPT_SIGNALED 0x00000004
+#define IB_SEND_OPT_SOLICITED 0x00000008
+#define IB_SEND_OPT_INLINE 0x00000010
+#define IB_SEND_OPT_LOCAL 0x00000020
+#define IB_SEND_OPT_VEND_MASK 0xFFFF0000
+/*
+* VALUES
+* The following flags determine the behavior of a work request when
+* posted to the send side.
+*
+* IB_SEND_OPT_IMMEDIATE
+* Send immediate data with the given request.
+*
+* IB_SEND_OPT_FENCE
+* The operation is fenced. Complete all pending send operations before
+* processing this request.
+*
+* IB_SEND_OPT_SIGNALED
+* If the queue pair is configured for signaled completion, then
+* generate a completion queue entry when this request completes.
+*
+* IB_SEND_OPT_SOLICITED
+* Set the solicited bit on the last packet of this request.
+*
+* IB_SEND_OPT_INLINE
+* Indicates that the requested send data should be copied into a VPD
+* owned data buffer. This flag permits the user to issue send operations
+* without first needing to register the buffer(s) associated with the
+* send operation. Verb providers that support this operation may place
+* vendor specific restrictions on the size of send operation that may
+* be performed as inline.
+*
+* IB_SEND_OPT_LOCAL
+* Indicates that a sent MAD request should be given to the local VPD for
+* processing. MADs sent using this option are not placed on the wire.
+* This send option is only valid for MAD send operations.
+*
+* IB_SEND_OPT_VEND_MASK
+* This mask indicates bits reserved in the send options that may be used
+* by the verbs provider to indicate vendor specific options. Bits set
+* in this area of the send options are ignored by the Access Layer, but
+* may have specific meaning to the underlying VPD.
+*
+*****/
+
+
+/****s* Access Layer/ib_send_wr_t
+* NAME
+* ib_send_wr_t
+*
+* DESCRIPTION
+* Information used to submit a work request to the send queue of a queue
+* pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_send_wr
+{
+ struct _ib_send_wr* __ptr64 p_next;
+ uint64_t wr_id;
+ ib_wr_type_t wr_type;
+ ib_send_opt_t send_opt;
+ uint32_t num_ds;
+ ib_local_ds_t* __ptr64 ds_array;
+ ib_net32_t immediate_data;
+
+ union _send_dgrm
+ {
+ struct _send_ud
+ {
+ ib_net32_t remote_qp;
+ ib_net32_t remote_qkey;
+ ib_av_handle_t h_av;
+ uint16_t pkey_index;
+ void* __ptr64 rsvd;
+
+ } ud;
+
+ struct _send_raw_ether
+ {
+ ib_net16_t dest_lid;
+ uint8_t path_bits;
+ uint8_t sl;
+ uint8_t max_static_rate;
+ ib_net16_t ether_type;
+
+ } raw_ether;
+
+ struct _send_raw_ipv6
+ {
+ ib_net16_t dest_lid;
+ uint8_t path_bits;
+ uint8_t sl;
+ uint8_t max_static_rate;
+
+ } raw_ipv6;
+
+ } dgrm;
+
+ struct _send_remote_ops
+ {
+ uint64_t vaddr;
+ net32_t rkey;
+
+ ib_net64_t atomic1;
+ ib_net64_t atomic2;
+
+ } remote_ops;
+
+} ib_send_wr_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work requests together. This permits multiple
+* work requests to be posted to a queue pair through a single function
+* call. This value is set to NULL to mark the end of the chain.
+*
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* wr_type
+* The type of work request being submitted to the send queue.
+*
+* send_opt
+* Optional send control parameters.
+*
+* num_ds
+* Number of local data segments specified by this work request.
+*
+* ds_array
+* A reference to an array of local data segments used by the send
+* operation.
+*
+* immediate_data
+* 32-bit field sent as part of a message send or RDMA write operation.
+* This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE
+* has been set.
+*
+* dgrm.ud.remote_qp
+* Identifies the destination queue pair of an unreliable datagram send
+* operation.
+*
+* dgrm.ud.remote_qkey
+* The qkey for the destination queue pair.
+*
+* dgrm.ud.h_av
+* An address vector that specifies the path information used to route
+* the outbound datagram to the destination queue pair.
+*
+* dgrm.ud.pkey_index
+* The pkey index for this send work request. This is valid only
+* for IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types. The work request
+* is posted to using this pkey index build the GMP's BTH instead
+* of the QP's pkey.
+*
+* dgrm.ud.rsvd
+* Reserved for use by the Access Layer.
+*
+* dgrm.raw_ether.dest_lid
+* The destination LID that will receive this raw ether send.
+*
+* dgrm.raw_ether.path_bits
+* path bits...
+*
+* dgrm.raw_ether.sl
+* service level...
+*
+* dgrm.raw_ether.max_static_rate
+* static rate...
+*
+* dgrm.raw_ether.ether_type
+* ether type...
+*
+* dgrm.raw_ipv6.dest_lid
+* The destination LID that will receive this raw ether send.
+*
+* dgrm.raw_ipv6.path_bits
+* path bits...
+*
+* dgrm.raw_ipv6.sl
+* service level...
+*
+* dgrm.raw_ipv6.max_static_rate
+* static rate...
+*
+* remote_ops.vaddr
+* The registered virtual memory address of the remote memory to access
+* with an RDMA or atomic operation.
+*
+* remote_ops.rkey
+* The rkey associated with the specified remote vaddr. This data must
+* be presented exactly as obtained from the remote node. No swapping
+* of data must be performed.
+*
+* atomic1
+* The first operand for an atomic operation.
+*
+* atomic2
+* The second operand for an atomic operation.
+*
+* NOTES
+* The format of data sent over the fabric is user-defined and is considered
+* opaque to the access layer. The sole exception to this are MADs posted
+* to a MAD QP service. MADs are expected to match the format defined by
+* the Infiniband specification and must be in network-byte order when posted
+* to the MAD QP service.
+*
+* SEE ALSO
+* ib_wr_type_t, ib_local_ds_t, ib_send_opt_t
+*****/
+
+
+/****s* Access Layer/ib_recv_wr_t
+* NAME
+* ib_recv_wr_t
+*
+* DESCRIPTION
+* Information used to submit a work request to the receive queue of a queue
+* pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_recv_wr
+{
+ struct _ib_recv_wr* __ptr64 p_next;
+ uint64_t wr_id;
+ uint32_t num_ds;
+ ib_local_ds_t* __ptr64 ds_array;
+
+} ib_recv_wr_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work requests together. This permits multiple
+* work requests to be posted to a queue pair through a single function
+* call. This value is set to NULL to mark the end of the chain.
+*
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* num_ds
+* Number of local data segments specified by this work request.
+*
+* ds_array
+* A reference to an array of local data segments used by the send
+* operation.
+*
+* SEE ALSO
+* ib_local_ds_t
+*****/
+
+
+/****s* Access Layer/ib_bind_wr_t
+* NAME
+* ib_bind_wr_t
+*
+* DESCRIPTION
+* Information used to submit a memory window bind work request to the send
+* queue of a queue pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_bind_wr
+{
+ uint64_t wr_id;
+ ib_send_opt_t send_opt;
+
+ ib_mr_handle_t h_mr;
+ ib_access_t access_ctrl;
+ net32_t current_rkey;
+
+ ib_local_ds_t local_ds;
+
+} ib_bind_wr_t;
+/*
+* FIELDS
+* wr_id
+* A 64-bit work request identifier that is returned to the consumer
+* as part of the work completion.
+*
+* send_opt
+* Optional send control parameters.
+*
+* h_mr
+* Handle to the memory region to which this window is being bound.
+*
+* access_ctrl
+* Access rights for this memory window.
+*
+* current_rkey
+* The current rkey assigned to this window for remote access.
+*
+* local_ds
+* A reference to a local data segment used by the bind operation.
+*
+* SEE ALSO
+* ib_send_opt_t, ib_access_t, ib_local_ds_t
+*****/
+
+
+/****d* Access Layer/ib_wc_status_t
+* NAME
+* ib_wc_status_t
+*
+* DESCRIPTION
+* Indicates the status of a completed work request. These VALUES are
+* returned to the user when retrieving completions. Note that success is
+* identified as IB_WCS_SUCCESS, which is always zero.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_status_t
+{
+ IB_WCS_SUCCESS,
+ IB_WCS_LOCAL_LEN_ERR,
+ IB_WCS_LOCAL_OP_ERR,
+ IB_WCS_LOCAL_PROTECTION_ERR,
+ IB_WCS_WR_FLUSHED_ERR,
+ IB_WCS_MEM_WINDOW_BIND_ERR,
+ IB_WCS_REM_ACCESS_ERR,
+ IB_WCS_REM_OP_ERR,
+ IB_WCS_RNR_RETRY_ERR,
+ IB_WCS_TIMEOUT_RETRY_ERR,
+ IB_WCS_REM_INVALID_REQ_ERR,
+ IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */
+ IB_WCS_CANCELED, /* InfiniBand Access Layer */
+ IB_WCS_UNKNOWN /* Must be last. */
+
+} ib_wc_status_t;
+/*
+* VALUES
+* IB_WCS_SUCCESS
+* Work request completed successfully.
+*
+* IB_WCS_MAD
+* The completed work request was associated with a managmenet datagram
+* that requires post processing. The MAD will be returned to the user
+* through a callback once all post processing has completed.
+*
+* IB_WCS_LOCAL_LEN_ERR
+* Generated for a work request posted to the send queue when the
+* total of the data segment lengths exceeds the message length of the
+* channel. Generated for a work request posted to the receive queue when
+* the total of the data segment lengths is too small for a
+* valid incoming message.
+*
+* IB_WCS_LOCAL_OP_ERR
+* An internal QP consistency error was generated while processing this
+* work request. This may indicate that the QP was in an incorrect state
+* for the requested operation.
+*
+* IB_WCS_LOCAL_PROTECTION_ERR
+* The data segments of the locally posted work request did not refer to
+* a valid memory region. The memory may not have been properly
+* registered for the requested operation.
+*
+* IB_WCS_WR_FLUSHED_ERR
+* The work request was flushed from the QP before being completed.
+*
+* IB_WCS_MEM_WINDOW_BIND_ERR
+* A memory window bind operation failed due to insufficient access
+* rights.
+*
+* IB_WCS_REM_ACCESS_ERR,
+* A protection error was detected at the remote node for a RDMA or atomic
+* operation.
+*
+* IB_WCS_REM_OP_ERR,
+* The operation could not be successfully completed at the remote node.
+* This may indicate that the remote QP was in an invalid state or
+* contained an invalid work request.
+*
+* IB_WCS_RNR_RETRY_ERR,
+* The RNR retry count was exceeded while trying to send this message.
+*
+* IB_WCS_TIMEOUT_RETRY_ERR
+* The local transport timeout counter expired while trying to send this
+* message.
+*
+* IB_WCS_REM_INVALID_REQ_ERR,
+* The remote node detected an invalid message on the channel. This error
+* is usually a result of one of the following:
+* - The operation was not supported on receive queue.
+* - There was insufficient buffers to receive a new RDMA request.
+* - There was insufficient buffers to receive a new atomic operation.
+* - An RDMA request was larger than 2^31 bytes.
+*
+* IB_WCS_UNMATCHED_RESPONSE
+* A response MAD was received for which there was no matching send. The
+* send operation may have been canceled by the user or may have timed
+* out.
+*
+* IB_WCS_CANCELED
+* The completed work request was canceled by the user.
+*****/
+
+
+
+/****f* IBA Base: Types/ib_get_wc_status_str
+* NAME
+* ib_get_wc_status_str
+*
+* DESCRIPTION
+* Returns a string for the specified work completion status.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_wc_status_str(
+ IN ib_wc_status_t wc_status );
+/*
+* PARAMETERS
+* wc_status
+* [in] work completion status value
+*
+* RETURN VALUES
+* Pointer to the work completion status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_wc_type_t
+* NAME
+* ib_wc_type_t
+*
+* DESCRIPTION
+* Indicates the type of work completion.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_type_t
+{
+ IB_WC_SEND,
+ IB_WC_RDMA_WRITE,
+ IB_WC_RECV,
+ IB_WC_RDMA_READ,
+ IB_WC_MW_BIND,
+ IB_WC_FETCH_ADD,
+ IB_WC_COMPARE_SWAP,
+ IB_WC_RECV_RDMA_WRITE,
+ IB_WC_UNKNOWN
+
+} ib_wc_type_t;
+/*****/
+
+
+/****f* IBA Base: Types/ib_get_wc_type_str
+* NAME
+* ib_get_wc_type_str
+*
+* DESCRIPTION
+* Returns a string for the specified work completion type.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_wc_type_str(
+ IN ib_wc_type_t wc_type );
+/*
+* PARAMETERS
+* wc_type
+* [in] work completion type value
+*
+* RETURN VALUES
+* Pointer to the work completion type description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_recv_opt_t
+* NAME
+* ib_recv_opt_t
+*
+* DESCRIPTION
+* Indicates optional fields valid in a receive work completion.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_recv_opt_t;
+#define IB_RECV_OPT_IMMEDIATE 0x00000001
+#define IB_RECV_OPT_FORWARD 0x00000002
+#define IB_RECV_OPT_GRH_VALID 0x00000004
+#define IB_RECV_OPT_VEND_MASK 0xFFFF0000
+/*
+* VALUES
+* IB_RECV_OPT_IMMEDIATE
+* Indicates that immediate data is valid for this work completion.
+*
+* IB_RECV_OPT_FORWARD
+* Indicates that the received trap should be forwarded to the SM.
+*
+* IB_RECV_OPT_GRH_VALID
+* Indicates presence of the global route header. When set, the first
+* 40 bytes received are the GRH.
+*
+* IB_RECV_OPT_VEND_MASK
+* This mask indicates bits reserved in the receive options that may be
+* used by the verbs provider to indicate vendor specific options. Bits
+* set in this area of the receive options are ignored by the Access Layer,
+* but may have specific meaning to the underlying VPD.
+*****/
+
+
+/****s* Access Layer/ib_wc_t
+* NAME
+* ib_wc_t
+*
+* DESCRIPTION
+* Work completion information.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_wc
+{
+ struct _ib_wc* __ptr64 p_next;
+ uint64_t wr_id;
+ ib_wc_type_t wc_type;
+
+ uint32_t length;
+ ib_wc_status_t status;
+ uint64_t vendor_specific;
+
+ union _wc_recv
+ {
+ struct _wc_conn
+ {
+ ib_recv_opt_t recv_opt;
+ ib_net32_t immediate_data;
+
+ } conn;
+
+ struct _wc_ud
+ {
+ ib_recv_opt_t recv_opt;
+ ib_net32_t immediate_data;
+ ib_net32_t remote_qp;
+ uint16_t pkey_index;
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+
+ } ud;
+
+ struct _wc_raw_ipv6
+ {
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+
+ } raw_ipv6;
+
+ struct _wc_raw_ether
+ {
+ ib_net16_t remote_lid;
+ uint8_t remote_sl;
+ uint8_t path_bits;
+ ib_net16_t ether_type;
+
+ } raw_ether;
+
+ } recv;
+
+} ib_wc_t;
+/*
+* FIELDS
+* p_next
+* A pointer used to chain work completions. This permits multiple
+* work completions to be retrieved from a completion queue through a
+* single function call. This value is set to NULL to mark the end of
+* the chain.
+*
+* wr_id
+* The 64-bit work request identifier that was specified when posting the
+* work request.
+*
+* wc_type
+* Indicates the type of work completion.
+*
+* length
+* The total length of the data sent or received with the work request.
+*
+* status
+* The result of the work request.
+*
+* vendor_specific
+* HCA vendor specific information returned as part of the completion.
+*
+* recv.conn.recv_opt
+* Indicates optional fields valid as part of a work request that
+* completed on a connected (reliable or unreliable) queue pair.
+*
+* recv.conn.immediate_data
+* 32-bit field received as part of an inbound message on a connected
+* queue pair. This field is only valid if the recv_opt flag
+* IB_RECV_OPT_IMMEDIATE has been set.
+*
+* recv.ud.recv_opt
+* Indicates optional fields valid as part of a work request that
+* completed on an unreliable datagram queue pair.
+*
+* recv.ud.immediate_data
+* 32-bit field received as part of an inbound message on a unreliable
+* datagram queue pair. This field is only valid if the recv_opt flag
+* IB_RECV_OPT_IMMEDIATE has been set.
+*
+* recv.ud.remote_qp
+* Identifies the source queue pair of a received datagram.
+*
+* recv.ud.pkey_index
+* The pkey index of the source queue pair. This is valid only for
+* IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types.
+*
+* recv.ud.remote_lid
+* The source LID of the received datagram.
+*
+* recv.ud.remote_sl
+* The service level used by the source of the received datagram.
+*
+* recv.ud.path_bits
+* path bits...
+*
+* recv.raw_ipv6.remote_lid
+* The source LID of the received message.
+*
+* recv.raw_ipv6.remote_sl
+* The service level used by the source of the received message.
+*
+* recv.raw_ipv6.path_bits
+* path bits...
+*
+* recv.raw_ether.remote_lid
+* The source LID of the received message.
+*
+* recv.raw_ether.remote_sl
+* The service level used by the source of the received message.
+*
+* recv.raw_ether.path_bits
+* path bits...
+*
+* recv.raw_ether.ether_type
+* ether type...
+* NOTES
+* When the work request completes with error, the only values that the
+* consumer can depend on are the wr_id field, and the status of the
+* operation.
+*
+* If the consumer is using the same CQ for completions from more than
+* one type of QP (i.e Reliable Connected, Datagram etc), then the consumer
+* must have additional information to decide what fields of the union are
+* valid.
+* SEE ALSO
+* ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t
+*****/
+
+
+/****s* Access Layer/ib_mr_create_t
+* NAME
+* ib_mr_create_t
+*
+* DESCRIPTION
+* Information required to create a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_create
+{
+ void* __ptr64 vaddr;
+ uint64_t length;
+ ib_access_t access_ctrl;
+
+} ib_mr_create_t;
+/*
+* FIELDS
+* vaddr
+* Starting virtual address of the region being registered.
+*
+* length
+* Length of the buffer to register.
+*
+* access_ctrl
+* Access rights of the registered region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_phys_range_t
+* NAME
+* ib_phys_range_t
+*
+* DESCRIPTION
+* Information describing a physical memory range.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_range
+{
+ uint64_t base_addr;
+ uint64_t size;
+
+} ib_phys_range_t;
+/*
+* FIELDS
+* base_addr
+* Physical address of the base of the memory range.
+*
+* size
+* size, in bytes, of the memory range.
+*
+* NOTES
+* The base address must be start and end on an HCA-supported page boundary.
+*
+* SEE ALSO
+* ib_phys_create_t
+*********/
+
+
+/****s* Access Layer/ib_phys_create_t
+* NAME
+* ib_phys_create_t
+*
+* DESCRIPTION
+* Information required to create a physical memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_create
+{
+ uint64_t length;
+ uint32_t num_ranges;
+ ib_phys_range_t* __ptr64 range_array;
+ uint32_t buf_offset;
+ uint32_t hca_page_size;
+ ib_access_t access_ctrl;
+
+} ib_phys_create_t;
+/*
+* FIELDS
+* length
+* The length of the memory region in bytes.
+*
+* num_ranges
+* Number of ib_phys_range structures listed in the specified range array.
+*
+* range_array
+* An array of ib_phys_range structures to be registered as a single memory
+* region.
+*
+* buf_offset
+* The offset into the first physical memory range of the specified memory
+* region on which to start the virtual address.
+*
+* hca_page_size
+* The HCA page size to use to register the memory.
+*
+* access_ctrl
+* Access rights of the registered region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_mr_attr_t
+* NAME
+* ib_mr_attr_t
+*
+* DESCRIPTION
+* Attributes of a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_attr
+{
+ ib_pd_handle_t h_pd;
+ uint64_t local_lb;
+ uint64_t local_ub;
+ uint64_t remote_lb;
+ uint64_t remote_ub;
+ ib_access_t access_ctrl;
+ net32_t lkey;
+ net32_t rkey;
+
+} ib_mr_attr_t;
+/*
+* DESCRIPTION
+* h_pd
+* Handle to the protection domain for this memory region.
+*
+* local_lb
+* The virtual address of the lower bound of protection for local
+* memory access. This is always a 64-bit quantity to support registering
+* more than 4GB of memory on 32-bit systems with PAE.
+*
+* local_ub
+* The virtual address of the upper bound of protection for local
+* memory access. This is always a 64-bit quantity to support registering
+* more than 4GB of memory on 32-bit systems with PAE.
+*
+* remote_lb
+* The virtual address of the lower bound of protection for remote
+* memory access. This is always a 64-bit quantity to support registering
+* more than 4GB of memory on 32-bit systems with PAE.
+*
+* remote_ub
+* The virtual address of the upper bound of protection for remote
+* memory access. This is always a 64-bit quantity to support registering
+* more than 4GB of memory on 32-bit systems with PAE.
+*
+* access_ctrl
+* Access rights for the specified memory region.
+*
+* lkey
+* The lkey associated with this memory region.
+*
+* rkey
+* The rkey associated with this memory region.
+*
+* NOTES
+* The remote_lb, remote_ub, and rkey are only valid if remote memory access
+* is enabled for this memory region.
+*
+* SEE ALSO
+* ib_access_t
+*****/
+
+
+/****d* Access Layer/ib_ca_mod_t
+* NAME
+* ib_ca_mod_t -- Modify port attributes and error counters
+*
+* DESCRIPTION
+* Specifies modifications to the port attributes of a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_ca_mod_t;
+#define IB_CA_MOD_IS_CM_SUPPORTED 0x00000001
+#define IB_CA_MOD_IS_SNMP_SUPPORTED 0x00000002
+#define IB_CA_MOD_IS_DEV_MGMT_SUPPORTED 0x00000004
+#define IB_CA_MOD_IS_VEND_SUPPORTED 0x00000008
+#define IB_CA_MOD_IS_SM 0x00000010
+#define IB_CA_MOD_IS_SM_DISABLED 0x00000020
+#define IB_CA_MOD_QKEY_CTR 0x00000040
+#define IB_CA_MOD_PKEY_CTR 0x00000080
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED 0x00000100
+#define IB_CA_MOD_IS_TRAP_SUPPORTED 0x00000200
+#define IB_CA_MOD_IS_APM_SUPPORTED 0x00000400
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED 0x00000800
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED 0x00001000
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED 0x00002000
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED 0x00004000
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED 0x00008000
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED 0x00010000
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED 0x00020000
+#define IB_CA_MOD_IS_REINIT_SUPORTED 0x00040000
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED 0x00080000
+#define IB_CA_MOD_SHUTDOWN_PORT 0x00100000
+#define IB_CA_MOD_INIT_TYPE_VALUE 0x00200000
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID 0x00400000
+/*
+* VALUES
+* IB_CA_MOD_IS_CM_SUPPORTED
+* Indicates if there is a communication manager accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SNMP_SUPPORTED
+* Indicates if there is an SNMP agent accessible through the port.
+*
+* IB_CA_MOD_IS_DEV_MGMT_SUPPORTED
+* Indicates if there is a device management agent accessible through
+* the port.
+*
+* IB_CA_MOD_IS_VEND_SUPPORTED
+* Indicates if there is a vendor supported agent accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SM
+* Indicates if there is a subnet manager accessible through
+* the port.
+*
+* IB_CA_MOD_IS_SM_DISABLED
+* Indicates if the port has been disabled for configuration by the subnet
+* manager.
+*
+* IB_CA_MOD_QKEY_CTR
+* Used to reset the qkey violation counter associated with the port.
+*
+* IB_CA_MOD_PKEY_CTR
+* Used to reset the pkey violation counter associated with the port.
+*
+* IB_CA_MOD_IS_NOTICE_SUPPORTED
+* Indicates that this CA supports ability to generate Notices for
+* Port State changes. (only applicable to switches)
+*
+* IB_CA_MOD_IS_TRAP_SUPPORTED
+* Indicates that this management port supports ability to generate
+* trap messages. (only applicable to switches)
+*
+* IB_CA_MOD_IS_APM_SUPPORTED
+* Indicates that this port is capable of performing Automatic Migration.
+*
+* IB_CA_MOD_IS_SLMAP_SUPPORTED
+* Indicates this port supports SLMAP capability.
+*
+* IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED
+* Indicates that PKEY is supported in NVRAM
+*
+* IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED
+* Indicates that MKEY is supported in NVRAM
+*
+* IB_CA_MOD_IS_SYSGUID_SUPPORTED
+* Indicates System Image GUID support.
+*
+* IB_CA_MOD_IS_DR_NOTICE_SUPPORTED
+* Indicate support for generating Direct Routed Notices
+*
+* IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED
+* Indicates support for Boot Management
+*
+* IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED
+* Indicates capability to generate notices for changes to CAPMASK
+*
+* IB_CA_MOD_IS_REINIT_SUPORTED
+* Indicates type of node init supported. Refer to Chapter 14 for
+* Initialization actions.
+*
+* IB_CA_MOD_IS_LEDINFO_SUPPORTED
+* Indicates support for LED info.
+*
+* IB_CA_MOD_SHUTDOWN_PORT
+* Used to modify the port active indicator.
+*
+* IB_CA_MOD_INIT_TYPE_VALUE
+* Used to modify the init_type value for the port.
+*
+* IB_CA_MOD_SYSTEM_IMAGE_GUID
+* Used to modify the system image GUID for the port.
+*****/
+
+
+/****d* Access Layer/ib_mr_mod_t
+* NAME
+* ib_mr_mod_t
+*
+* DESCRIPTION
+* Mask used to specify which attributes of a registered memory region are
+* being modified.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_mr_mod_t;
+#define IB_MR_MOD_ADDR 0x00000001
+#define IB_MR_MOD_PD 0x00000002
+#define IB_MR_MOD_ACCESS 0x00000004
+/*
+* PARAMETERS
+* IB_MEM_MOD_ADDR
+* The address of the memory region is being modified.
+*
+* IB_MEM_MOD_PD
+* The protection domain associated with the memory region is being
+* modified.
+*
+* IB_MEM_MOD_ACCESS
+* The access rights the memory region are being modified.
+*****/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT
+* NAME
+* IB_SMINFO_STATE_INIT
+*
+* DESCRIPTION
+* Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_INIT 4
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER
+* NAME
+* IB_SMINFO_ATTR_MOD_HANDOVER
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_HANDOVER (CL_NTOH32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+* NAME
+* IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE (CL_NTOH32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE
+* NAME
+* IB_SMINFO_ATTR_MOD_DISABLE
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISABLE (CL_NTOH32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY
+* NAME
+* IB_SMINFO_ATTR_MOD_STANDBY
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_STANDBY (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER
+* NAME
+* IB_SMINFO_ATTR_MOD_DISCOVER
+*
+* DESCRIPTION
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISCOVER (CL_NTOH32(0x000005))
+/**********/
+
+/****s* Access Layer/ib_ci_op_t
+* NAME
+* ib_ci_op_t
+*
+* DESCRIPTION
+* A structure used for vendor specific CA interface communication.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ci_op
+{
+ IN uint32_t command;
+ IN uint32_t buf_size;
+ IN uint32_t buf_info;
+ IN OUT int32_t status;
+ OUT uint32_t num_bytes_ret;
+ IN OUT void* __ptr64 p_buf OPTIONAL;
+
+} ib_ci_op_t;
+/*
+* FIELDS
+* command
+* A command code that is understood by the verbs provider.
+*
+* status
+* The completion status from the verbs provider. This field should be
+* initialize to indicate an error to allow detection and cleanup in
+* case a communication error occurs between user-mode and kernel-mode.
+*
+* buf_size
+* The size of the buffer in bytes.
+*
+* buf_info
+* Additional buffer information
+*
+* p_buf
+* A reference to a buffer containing vendor specific data. The verbs
+* provider must not access pointers in the p_buf between user-mode and
+* kernel-mode. Any pointers embedded in the p_buf are invalidated by
+* the user-mode/kernel-mode transition.
+*
+* num_bytes_ret
+* The size in bytes of the vendor specific data returned in the buffer.
+* This field is set by the verbs provider. The verbs provider should
+* verify that the buffer size is sufficient to hold the data being
+* returned.
+*
+* NOTES
+* This structure is provided to allow the exchange of vendor specific
+* data between the originator and the verbs provider. Users of this
+* structure are expected to know the format of data in the p_buf based
+* on the structure command field or the usage context.
+*****/
+
+
+#endif // __IB_TYPES_EXTENDED_H__
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of dispatcher abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_threadpool.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_ptr_vector.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Dispatcher
+* NAME
+* Dispatcher
+*
+* DESCRIPTION
+* The Dispatcher provides a facility for message routing to
+* asynchronous worker threads.
+*
+* The Dispatcher functions operate on a cl_dispatcher_t structure
+* which should be treated as opaque and should be manipulated
+* only through the provided functions.
+*
+* SEE ALSO
+* Structures:
+* cl_dispatcher_t
+*
+* Initialization/Destruction:
+* cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy
+*
+* Manipulation:
+* cl_disp_post, cl_disp_reset, cl_disp_wait_on
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_msgid_t
+* NAME
+* cl_disp_msgid_t
+*
+* DESCRIPTION
+* Defines the type of dispatcher messages.
+*
+* SYNOPSIS
+*/
+typedef uint32_t cl_disp_msgid_t;
+/**********/
+
+
+/****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE
+* NAME
+* CL_DISP_MSGID_NONE
+*
+* DESCRIPTION
+* Defines a message value that means "no message".
+* This value is used during registration by Dispatcher clients
+* that do not wish to receive messages.
+*
+* No Dispatcher message is allowed to have this value.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_MSGID_NONE 0xFFFFFFFF
+/**********/
+
+/****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE
+* NAME
+* CL_DISP_INVALID_HANDLE
+*
+* DESCRIPTION
+* Defines the value of an invalid Dispatcher registration handle.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0)
+/*********/
+
+/****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t
+* NAME
+* cl_pfn_msgrcv_cb_t
+*
+* DESCRIPTION
+* This typedef defines the prototype for client functions invoked
+* by the Dispatcher. The Dispatcher calls the corresponding
+* client function when delivering a message to the client.
+*
+* The client function must be reentrant if the user creates a
+* Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void
+(*cl_pfn_msgrcv_cb_t)(
+ IN void* context,
+ IN void* p_data );
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in a call to
+* cl_disp_register
+*
+* p_data
+* [in] Pointer to the client specific data payload
+* of this message.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* This typedef provides a function prototype reference for
+* the function provided by Dispatcher clients as a parameter
+* to the cl_disp_register function.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_register
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t
+* NAME
+* cl_pfn_msgdone_cb_t
+*
+* DESCRIPTION
+* This typedef defines the prototype for client functions invoked
+* by the Dispatcher. The Dispatcher calls the corresponding
+* client function after completing delivery of a message.
+*
+* The client function must be reentrant if the user creates a
+* Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void
+(*cl_pfn_msgdone_cb_t)(
+ IN void* context,
+ IN void* p_data );
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in a call to
+* cl_disp_post
+*
+* p_data
+* [in] Pointer to the client specific data payload
+* of this message.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* This typedef provides a function prototype reference for
+* the function provided by Dispatcher clients as a parameter
+* to the cl_disp_post function.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_post
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_dispatcher_t
+* NAME
+* cl_dispatcher_t
+*
+* DESCRIPTION
+* Dispatcher structure.
+*
+* The Dispatcher is thread safe.
+*
+* The cl_dispatcher_t structure should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_dispatcher
+{
+ cl_spinlock_t lock;
+ cl_ptr_vector_t reg_vec;
+ cl_qlist_t reg_list;
+ cl_thread_pool_t worker_threads;
+ cl_qlist_t msg_fifo;
+ cl_qpool_t msg_pool;
+ uint64_t last_msg_queue_time_us;
+} cl_dispatcher_t;
+/*
+* FIELDS
+* reg_vec
+* Vector of registration info objects. Indexed by message msg_id.
+*
+* lock
+* Spinlock to guard internal structures.
+*
+* msg_fifo
+* FIFO of messages being processed by the Dispatcher. New
+* messages are posted to the tail of the FIFO. Worker threads
+* pull messages from the front.
+*
+* worker_threads
+* Thread pool of worker threads to dispose of posted messages.
+*
+* msg_pool
+* Pool of message objects to be processed through the FIFO.
+*
+* reg_count
+* Count of the number of registrants.
+*
+* state
+* Indicates the state of the object.
+*
+* last_msg_queue_time_us
+* The time that the last message spent in the Q in usec
+*
+* SEE ALSO
+* Dispatcher
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+* cl_disp_reg_info_t
+*
+* DESCRIPTION
+* Defines the dispatcher registration object structure.
+*
+* The cl_disp_reg_info_t structure is for internal use by the
+* Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_reg_info
+{
+ cl_list_item_t list_item;
+ cl_pfn_msgrcv_cb_t pfn_rcv_callback;
+ const void *context;
+ atomic32_t ref_cnt;
+ cl_disp_msgid_t msg_id;
+ cl_dispatcher_t *p_disp;
+
+} cl_disp_reg_info_t;
+/*
+* FIELDS
+* pfn_rcv_callback
+* Client's message receive callback.
+*
+* context
+* Client's context for message receive callback.
+*
+* rcv_thread_count
+* Number of threads currently in the receive callback.
+*
+* msg_done_thread_count
+* Number of threads currently in the message done callback.
+*
+* state
+* State of this registration object.
+* DISP_REGSTATE_INIT: initialized and inactive
+* DISP_REGSTATE_ACTIVE: in active use
+* DISP_REGSTATE_UNREGPEND: unregistration is pending
+*
+* msg_id
+* Dispatcher message msg_id value for this registration object.
+*
+* p_disp
+* Pointer to parent Dispatcher.
+*
+* SEE ALSO
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_msg_t
+* NAME
+* cl_disp_msg_t
+*
+* DESCRIPTION
+* Defines the dispatcher message structure.
+*
+* The cl_disp_msg_t structure is for internal use by the
+* Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_msg
+{
+ cl_pool_item_t item;
+ const void *p_data;
+ cl_disp_reg_info_t *p_src_reg;
+ cl_disp_reg_info_t *p_dest_reg;
+ cl_pfn_msgdone_cb_t pfn_xmt_callback;
+ uint64_t in_time;
+ const void *context;
+} cl_disp_msg_t;
+/*
+* FIELDS
+* item
+* List & Pool linkage. Must be first element in the structure!!
+*
+* msg_id
+* The message's numberic ID value.
+*
+* p_data
+* Pointer to the data payload for this message. The payload
+* is opaque to the Dispatcher.
+*
+* p_reg_info
+* Pointer to the registration info of the sender.
+*
+* pfn_xmt_callback
+* Client's message done callback.
+*
+* in_time
+* The absolute time the message was inserted into the queue
+*
+* context
+* Client's message done callback context.
+*
+* SEE ALSO
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+* cl_disp_reg_info_t
+*
+* DESCRIPTION
+* Defines the Dispatcher registration handle. This handle
+* should be treated as opaque by the client.
+*
+* SYNOPSIS
+*/
+typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t;
+/**********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_construct
+* NAME
+* cl_disp_construct
+*
+* DESCRIPTION
+* This function constructs a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_construct(
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_disp
+* [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling cl_disp_init and cl_disp_destroy.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_init, cl_disp_destroy
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_init
+* NAME
+* cl_disp_init
+*
+* DESCRIPTION
+* This function initializes a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_init(
+ IN cl_dispatcher_t* const p_disp,
+ IN const uint32_t thread_count,
+ IN const char* const name );
+/*
+* PARAMETERS
+* p_disp
+* [in] Pointer to a Dispatcher.
+*
+* thread_count
+* [in] The number of worker threads to create in this Dispatcher.
+* A value of 0 causes the Dispatcher to create one worker thread
+* per CPU in the system. When the Dispatcher is created with
+* only one thread, the Dispatcher guarantees to deliver posted
+* messages in order. When the Dispatcher is created with more
+* than one thread, messages may be delivered out of order.
+*
+* name
+* [in] Name to associate with the threads. The name may be up to 16
+* characters, including a terminating null character. All threads
+* created in the Dispatcher have the same name.
+*
+* RETURN VALUE
+* CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister,
+* cl_disp_post
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_shutdown
+* NAME
+* cl_disp_shutdown
+*
+* DESCRIPTION
+* This function shutdown a Dispatcher object. So it unreg all messages and
+* clears the fifo and waits for the threads to exit
+*
+* SYNOPSIS
+*/
+void
+cl_disp_shutdown(
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_disp
+* [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* This function does not returns until all worker threads
+* have exited client callback functions and been successfully
+* shutdowned.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_destroy
+* NAME
+* cl_disp_destroy
+*
+* DESCRIPTION
+* This function destroys a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_destroy(
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_disp
+* [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_register
+* NAME
+* cl_disp_register
+*
+* DESCRIPTION
+* This function registers a client with a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_disp_reg_handle_t
+cl_disp_register(
+ IN cl_dispatcher_t* const p_disp,
+ IN const cl_disp_msgid_t msg_id,
+ IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL,
+ IN const void* const context );
+/*
+* PARAMETERS
+* p_disp
+* [in] Pointer to a Dispatcher.
+*
+* msg_id
+* [in] Numberic message ID for which the client is registering.
+* If the client does not wish to receive any messages,
+* (a send-only client) then the caller should set this value
+* to CL_DISP_MSGID_NONE. For efficiency, numeric message msg_id
+* values should start with 0 and should be contiguous, or nearly so.
+*
+* pfn_callback
+* [in] Message receive callback. The Dispatcher calls this
+* function after receiving a posted message with the
+* appropriate message msg_id value. Send-only clients may specify
+* NULL for this value.
+*
+* context
+* [in] Client context value passed to the cl_pfn_msgrcv_cb_t
+* function.
+*
+* RETURN VALUE
+* On success a Dispatcher registration handle.
+* CL_CL_DISP_INVALID_HANDLE otherwise.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_unregister, cl_disp_post
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_unregister
+* NAME
+* cl_disp_unregister
+*
+* DESCRIPTION
+* This function unregisters a client from a Dispatcher.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_unregister(
+ IN const cl_disp_reg_handle_t handle );
+/*
+* PARAMETERS
+* handle
+* [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* This function will not return until worker threads have exited
+* the callback functions for this client. Do not invoke this
+* function from a callback.
+*
+* SEE ALSO
+* Dispatcher, cl_disp_register
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_post
+* NAME
+* cl_disp_post
+*
+* DESCRIPTION
+* This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_post(
+ IN const cl_disp_reg_handle_t handle,
+ IN const cl_disp_msgid_t msg_id,
+ IN const void* const p_data,
+ IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL,
+ IN const void* const context );
+/*
+* PARAMETERS
+* handle
+* [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+* msg_id
+* [in] Numeric message msg_id value associated with this message.
+*
+* p_data
+* [in] Data payload for this message.
+*
+* pfn_callback
+* [in] Pointer to a cl_pfn_msgdone_cb_t function.
+* The Dispatcher calls this function after the message has been
+* processed by the recipient.
+* The caller may pass NULL for this value, which indicates no
+* message done callback is necessary.
+*
+* context
+* [in] Client context value passed to the cl_pfn_msgdone_cb_t
+* function.
+*
+* RETURN VALUE
+* CL_SUCCESS if the message was successfully queued in the Dispatcher.
+*
+* NOTES
+* The caller must not modify the memory pointed to by p_data until
+* the Dispatcher call the pfn_callback function.
+*
+* SEE ALSO
+* Dispatcher
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_get_queue_status
+* NAME
+* cl_disp_get_queue_status
+*
+* DESCRIPTION
+* This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_get_queue_status(
+ IN const cl_disp_reg_handle_t handle,
+ OUT uint32_t *p_num_queued_msgs,
+ OUT uint64_t *p_last_msg_queue_time_ms);
+/*
+* PARAMETERS
+* handle
+* [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+* p_last_msg_queue_time_ms
+* [out] pointer to a variable to hold the time the last popped up message
+* spent in the queue
+*
+* p_num_queued_msgs
+* [out] number of messages in the queue
+*
+* RETURN VALUE
+* Thr time the last popped up message stayed in the queue, in msec
+*
+* NOTES
+* Extarnel Locking is not required.
+*
+* SEE ALSO
+* Dispatcher
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_DISPATCHER_H_) */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of event wheel abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Event_Wheel
+* NAME
+* Event_Wheel
+*
+* DESCRIPTION
+* The Event_Wheel provides a facility for registering delayed events
+* and getting called once they timeout.
+*
+* The Event_Wheel functions operate on a cl_event_wheel_t structure
+* which should be treated as opaque and should be manipulated
+* only through the provided functions.
+*
+* SEE ALSO
+* Structures:
+* cl_event_wheel_t
+*
+* Initialization/Destruction:
+* cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy
+*
+* Manipulation:
+* cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t
+* NAME
+* cl_pfn_event_aged_cb_t
+*
+* DESCRIPTION
+* This typedef defines the prototype for client functions invoked
+* by the Event_Wheel. The Event_Wheel calls the corresponding
+* client function when the specific item has aged.
+*
+* SYNOPSIS
+*/
+typedef uint64_t
+(*cl_pfn_event_aged_cb_t)(
+ IN uint64_t key,
+ IN uint32_t num_regs,
+ IN void* context);
+/*
+* PARAMETERS
+* key
+* [in] The key used for registering the item in the call to
+* cl_event_wheel_reg
+*
+* num_regs
+* [in] The number of times this event was registered (pushed in time).
+*
+* context
+* [in] Client specific context specified in a call to
+* cl_event_wheel_reg
+*
+* RETURN VALUE
+* This function returns the abosolute time the event should fire in [usec].
+* If lower then current time means the event should be unregistered
+* immediatly.
+*
+* NOTES
+* This typedef provides a function prototype reference for
+* the function provided by Event_Wheel clients as a parameter
+* to the cl_event_wheel_reg function.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_t
+* NAME
+* cl_event_wheel_t
+*
+* DESCRIPTION
+* Event_Wheel structure.
+*
+* The Event_Wheel is thread safe.
+*
+* The cl_event_wheel_t structure should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel
+{
+ cl_spinlock_t lock;
+ cl_spinlock_t *p_external_lock;
+
+ cl_qmap_t events_map;
+ boolean_t closing;
+ cl_qlist_t events_wheel;
+ cl_timer_t timer;
+ osm_log_t *p_log;
+} cl_event_wheel_t;
+/*
+* FIELDS
+* lock
+* Spinlock to guard internal structures.
+*
+* p_external_lock
+* Reference to external spinlock to guard internal structures
+* if the event wheel is part of a larger object protected by its own lock
+*
+* events_map
+* A Map holding all registered event items by their key.
+*
+* closing
+* A flag indicating the event wheel is closing. This means that
+* callbacks that are called when closing == TRUE should just be ignored.
+*
+* events_wheel
+* A list of the events sorted by expiration time.
+*
+* timer
+* The timer scheduling event time propagation.
+*
+* p_log
+* Pointer to opensm log object.
+*
+* SEE ALSO
+* Event_Wheel
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t
+* NAME
+* cl_event_wheel_reg_info_t
+*
+* DESCRIPTION
+* Defines the event_wheel registration object structure.
+*
+* The cl_event_wheel_reg_info_t structure is for internal use by the
+* Event_Wheel only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel_reg_info
+{
+ cl_map_item_t map_item;
+ cl_list_item_t list_item;
+ uint64_t key;
+ cl_pfn_event_aged_cb_t pfn_aged_callback;
+ uint64_t aging_time;
+ uint32_t num_regs;
+ void *context;
+ cl_event_wheel_t *p_event_wheel;
+} cl_event_wheel_reg_info_t;
+/*
+* FIELDS
+* map_item
+* The map item of this event
+*
+* list_item
+* The sorted by aging time list item
+*
+* key
+* The key by which one can find the event
+*
+* pfn_aged_callback
+* The clients Event-Aged callback
+*
+* aging_time
+* The delta time [msec] for which the event should age.
+*
+* num_regs
+* The number of times the same event (key) was registered
+*
+* context
+* Client's context for event-aged callback.
+*
+* p_event_wheel
+* Pointer to this event wheel object
+*
+* SEE ALSO
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_construct
+* NAME
+* cl_event_wheel_construct
+*
+* DESCRIPTION
+* This function constructs a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_construct(
+ IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling cl_event_wheel_init and cl_event_wheel_destroy.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+* cl_event_wheel_init
+*
+* DESCRIPTION
+* This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN osm_log_t *p_log);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* RETURN VALUE
+* CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+* cl_event_wheel_init
+*
+* DESCRIPTION
+* This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init_ex(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN osm_log_t *p_log,
+ IN cl_spinlock_t *p_external_lock);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* p_external_lock
+* [in] Reference to external spinlock to guard internal structures
+* if the event wheel is part of a larger object protected by its own lock
+*
+* RETURN VALUE
+* CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_destroy
+* NAME
+* cl_event_wheel_destroy
+*
+* DESCRIPTION
+* This function destroys a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_destroy(
+ IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* This function does not returns until all client callback functions
+* been successfully finished.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_dump
+* NAME
+* cl_event_wheel_dump
+*
+* DESCRIPTION
+* This function dumps the details of an Event_Whell object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_dump(
+ IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Note that this function should be called inside a lock of the event wheel!
+* It doesn't aquire the lock by itself.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_reg
+* NAME
+* cl_event_wheel_reg
+*
+* DESCRIPTION
+* This function registers a client with a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_reg(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN const uint64_t key,
+ IN const uint64_t aging_time_usec,
+ IN cl_pfn_event_aged_cb_t pfn_callback,
+ IN void* const context );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* key
+* [in] The specifc Key by which events are registered.
+*
+* aging_time_usec
+* [in] The absolute time this event should age in usec
+*
+* pfn_callback
+* [in] Event Aging callback. The Event_Wheel calls this
+* function after the time the event has registed for has come.
+*
+* context
+* [in] Client context value passed to the cl_pfn_event_aged_cb_t
+* function.
+*
+* RETURN VALUE
+* On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_unreg
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_unreg
+* NAME
+* cl_event_wheel_unreg
+*
+* DESCRIPTION
+* This function unregisters a client event from a Event_Wheel.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_unreg(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN uint64_t key );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* key
+* [in] The key used for registering the event
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* After the event has aged it is automatically removed from
+* the event wheel. So it should only be invoked when the need arises
+* to remove existing events before they age.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs
+* NAME
+* cl_event_wheel_num_regs
+*
+* DESCRIPTION
+* This function returns the number of times an event was registered.
+*
+* SYNOPSIS
+*/
+uint32_t
+cl_event_wheel_num_regs(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN uint64_t key );
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* key
+* [in] The key used for registering the event
+*
+* RETURN VALUE
+* The number of times the event was registered.
+* 0 if never registered or eventually aged.
+*
+* SEE ALSO
+* Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_EVENT_WHEEL_H_) */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_ATTRIB_REQ_H_
+#define _OSM_ATTRIB_REQ_H_
+
+#include <opensm/osm_path.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ * Declaration of the attribute request object. This object
+ * encapsulates information needed by the generic request controller
+ * to request an attribute from a node.
+ * These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****h* OpenSM/Attribute Request
+* NAME
+* Attribute Request
+*
+* DESCRIPTION
+* The Attribute Request structure encapsulates
+* encapsulates information needed by the generic request controller
+* to request an attribute from a node.
+*
+* This structure allows direct access to member variables.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Attribute Request/osm_attrib_req_t
+* NAME
+* osm_attrib_req_t
+*
+* DESCRIPTION
+* Attribute request structure.
+*
+* This structure allows direct access to member variables.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_attrib_req
+{
+ uint16_t attrib_id;
+ uint32_t attrib_mod;
+ osm_madw_context_t context;
+ osm_dr_path_t path;
+ cl_disp_msgid_t err_msg;
+
+} osm_attrib_req_t;
+/*
+* FIELDS
+* attrib_id
+* Attribute ID for this request.
+*
+* attrib_mod
+* Attribute modifier for this request.
+*
+* context
+* Context to insert in outbound mad wrapper context.
+*
+* path
+* The directed route path to the node.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_ATTRIB_REQ_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Basic OpenSM definitions and structures.
+ * This object represents an OpenSM "base class".
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#ifndef _OSM_BASE_H_
+#define _OSM_BASE_H_
+
+#ifdef __WIN__
+#include <vendor/winosm_common.h>
+#define OSM_CDECL __cdecl
+#else
+#define OSM_CDECL
+#endif
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Constants
+* NAME
+* Constants
+*
+* DESCRIPTION
+* The following constants are used throughout the OpenSM.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****h* OpenSM/Base
+* NAME
+* Base
+*
+* DESCRIPTION
+* The Base object encapsulates basic information needed by the
+* OpenSM to manage objects. Each OpenSM object includes the
+* Base object as the first member.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+* OSM_VERSION
+*
+* DESCRIPTION
+* The version String for OpenSM
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-1.1.0"
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY
+* NAME
+* OSM_DEFAULT_M_KEY
+*
+* DESCRIPTION
+* Managment key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_M_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY
+* NAME
+* OSM_DEFAULT_SM_KEY
+*
+* DESCRIPTION
+* Subnet Manager key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_LMC
+* NAME
+* OSM_DEFAULT_LMC
+*
+* DESCRIPTION
+* Default LMC value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LMC 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS
+* NAME
+* OSM_DEFAULT_MAX_OP_VLS
+*
+* DESCRIPTION
+* Default Maximal Operational VLs to be initialized on
+* the link ports PortInfo by the OpenSM.
+* Default value provides backward compatibility.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MAX_OP_VLS 5
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SL
+* NAME
+* OSM_DEFAULT_SL
+*
+* DESCRIPTION
+* Default SL value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SL 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY
+* NAME
+* OSM_DEFAULT_SM_PRIORITY
+*
+* DESCRIPTION
+* Default SM priority value used by the OpenSM,
+* as defined in the SMInfo attribute. 0 is the highest priority.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_PRIORITY 0
+/********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR
+* NAME
+* OSM_DEFAULT_TMP_DIR
+*
+* DESCRIPTION
+* Specifies the default temporary directory for the log file, subnet.lst
+* and the other log files (with the exception of osm.log for Linux being
+* in /var/log).
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_TMP_DIR GetOsmPath()
+#else
+#define OSM_DEFAULT_TMP_DIR "/tmp/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR
+* NAME
+* OSM_DEFAULT_CACHE_DIR
+*
+* DESCRIPTION
+* Specifies the default cache directory for the db files.
+* Note that the directory must appear with "/" ("\\" for windows) at the end.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CACHE_DIR GetOsmPath()
+#else
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE
+* NAME
+* OSM_DEFAULT_LOG_FILE
+*
+* DESCRIPTION
+* Specifies the default log file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_LOG_FILE strcat(GetOsmPath(),"osm.log")
+#else
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
+* NAME
+* OSM_DEFAULT_SWEEP_INTERVAL_SECS
+*
+* DESCRIPTION
+* Specifies the default number of seconds between subnet sweeps.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+* NAME
+* OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+*
+* DESCRIPTION
+* Specifies the default transaction timeout in milliseconds.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 100
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT
+* NAME
+* OSM_DEFAULT_SUBNET_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default transaction timeout.
+* timeout time = 4us * 2^timeout.
+* We use here ~1sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE
+* NAME
+* OSM_DEFAULT_SWITCH_PACKET_LIFE
+*
+* DESCRIPTION
+* Specifies the default max life time for a pcket on the switch.
+* timeout time = 4us * 2^timeout.
+* We use here the value of ~1sec
+* A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+* NAME
+* OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+* Sets the time a packet can live in the head of the VL Queue
+* We use here the value of ~1sec
+* A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+* NAME
+* OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+* Sets the time a packet can live in the head of the VL Queue
+* of a port that drives a CA port.
+* We use here the value of ~130usec
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT
+* NAME
+* OSM_DEFAULT_LEAF_VL_STALL_COUNT
+*
+* DESCRIPTION
+* Sets the number of contigious head of queue life time drops that
+* puts the VL into stalled state. In stalled state the port supposed to
+* drop everything for 8*(head of queue lifetime)
+* We use here the value of 1 - so any drop due to HOQ means stalling the VL
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+* NAME
+* OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default timeout for ignoring same trap.
+* timeout time = 5000000us
+* We use here ~5sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT
+* NAME
+* OSM_DEFAULT_UNHEALTHY_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default timeout for setting port as un-healthy.
+* timeout time = 60000000us
+* We use here ~60sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD
+* NAME
+* OSM_DEFAULT_ERROR_THRESHOLD
+*
+* DESCRIPTION
+* Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE
+* NAME
+* OSM_DEFAULT_SMP_MAX_ON_WIRE
+*
+* DESCRIPTION
+* Specifies the default number of VL15 SMP MADs allowed on
+* the wire at any one time.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 1
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP0_RCV_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP0 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP0_SEND_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP0 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256
+
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+* NAME
+* OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+*
+* DESCRIPTION
+* Specifies the polling timeout (in miliseconds) - the timeout
+* between one poll to another.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000
+/**********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+* NAME
+* OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+*
+* DESCRIPTION
+* Specifies the number of polling retries before the SM goes back
+* to DISCOVERY stage. So the total time for handoff is 3min.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 18
+/**********/
+
+/****d* OpenSM: Base/OSM_NO_PATH
+* NAME
+* OSM_NO_PATH
+*
+* DESCRIPTION
+* Value indicating there is no path to the given LID.
+*
+* SYNOPSIS
+*/
+#define OSM_NO_PATH 0xFF
+/**********/
+
+/****d* OpenSM: Base/osm_thread_state_t
+* NAME
+* osm_thread_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of worker threads, such
+* as the subnet sweeper.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_thread_state
+{
+ OSM_THREAD_STATE_NONE = 0,
+ OSM_THREAD_STATE_INIT,
+ OSM_THREAD_STATE_RUN,
+ OSM_THREAD_STATE_EXIT
+
+} osm_thread_state_t;
+/***********/
+
+/*
+ * OSM_CAP ARE C15-0.1.7 Table 152
+ */
+
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP
+* Name
+* OSM_CAP_IS_SUBN_OPT_RECS_SUP
+*
+* DESCRIPTION
+* Support all optional attributes not including:
+* MCMemberRecord, TraceRecord, MultPiathRecord
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP
+* Name
+* OSM_CAP_IS_UD_MCAST_SUP
+*
+* DESCRIPTION
+* Multicast is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_MULTI_PATH_SUP
+* Name
+* OSM_CAP_IS_MULTI_PATH_SUP
+*
+* DESCRIPTION
+* Multi Path is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_MULTI_PATH_SUP (1 << 10);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP
+* Name
+* OSM_CAP_IS_REINIT_SUP
+*
+* DESCRIPTION
+* SM/SA supports re-initialization supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_REINIT_SUP (1 << 11);
+/***********/
+
+/****d* OpenSM: Base/osm_sm_state_t
+* NAME
+* osm_sm_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of the SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_state
+{
+ OSM_SM_STATE_NO_STATE = 0,
+ OSM_SM_STATE_INIT,
+ OSM_SM_STATE_IDLE,
+ OSM_SM_STATE_SWEEP_LIGHT,
+ OSM_SM_STATE_SWEEP_LIGHT_WAIT,
+ OSM_SM_STATE_SWEEP_HEAVY_SELF,
+ OSM_SM_STATE_SWEEP_HEAVY_SUBNET,
+ OSM_SM_STATE_SET_SM_UCAST_LID,
+ OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,
+ OSM_SM_STATE_SET_SM_UCAST_LID_DONE,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,
+ OSM_SM_STATE_SET_UCAST_TABLES,
+ OSM_SM_STATE_SET_UCAST_TABLES_WAIT,
+ OSM_SM_STATE_SET_UCAST_TABLES_DONE,
+ OSM_SM_STATE_SET_MCAST_TABLES,
+ OSM_SM_STATE_SET_MCAST_TABLES_WAIT,
+ OSM_SM_STATE_SET_MCAST_TABLES_DONE,
+ OSM_SM_STATE_SET_LINK_PORTS,
+ OSM_SM_STATE_SET_LINK_PORTS_WAIT,
+ OSM_SM_STATE_SET_LINK_PORTS_DONE,
+ OSM_SM_STATE_SET_ARMED,
+ OSM_SM_STATE_SET_ARMED_WAIT,
+ OSM_SM_STATE_SET_ARMED_DONE,
+ OSM_SM_STATE_SET_ACTIVE,
+ OSM_SM_STATE_SET_ACTIVE_WAIT,
+ OSM_SM_STATE_LOST_NEGOTIATION,
+ OSM_SM_STATE_STANDBY,
+ OSM_SM_STATE_SUBNET_UP,
+ OSM_SM_STATE_PROCESS_REQUEST,
+ OSM_SM_STATE_PROCESS_REQUEST_WAIT,
+ OSM_SM_STATE_PROCESS_REQUEST_DONE,
+ OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,
+ OSM_SM_STATE_MAX
+
+} osm_sm_state_t;
+/***********/
+
+/****d* OpenSM: Base/osm_signal_t
+* NAME
+* osm_signal_t
+*
+* DESCRIPTION
+* Enumerates the possible signal codes used by the OSM managers
+* This cannot be an enum type, since conversion to and from
+* integral types is necessary when passing signals through
+* the dispatcher.
+*
+* SYNOPSIS
+*/
+#define OSM_SIGNAL_NONE 0
+#define OSM_SIGNAL_SWEEP 1
+#define OSM_SIGNAL_CHANGE_DETECTED 2
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS 3
+#define OSM_SIGNAL_DONE 4
+#define OSM_SIGNAL_DONE_PENDING 5
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION 6
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL 7
+#define OSM_SIGNAL_IDLE_TIME_PROCESS 8
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST 9
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED 10
+#define OSM_SIGNAL_EXIT_STBY 11
+#define OSM_SIGNAL_MAX 12
+
+typedef uintn_t osm_signal_t;
+/***********/
+
+/****d* OpenSM: Base/osm_state_mgr_mode_t
+* NAME
+* osm_state_mgr_mode_t
+*
+* DESCRIPTION
+* Enumerates the possible state progressing codes used by the OSM
+* state manager.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_state_mgr_mode
+{
+ OSM_STATE_STEP_CONTINUOUS = 0,
+ OSM_STATE_STEP_TAKE_ONE,
+ OSM_STATE_STEP_BREAK
+} osm_state_mgr_mode_t;
+/*
+* OSM_STATE_STEP_CONTINUOUS
+* normal automatic progress mode
+*
+* OSM_STATE_STEP_TAKE_ONE
+* Do one step
+*
+* OSM_STATE_STEP_BREAK
+* Stop before taking next step (the while loop in the state
+* manager automatically change to this state).
+*
+**********/
+
+#define OSM_REPORT_BUF_SIZE 0x10000
+#define OSM_REPORT_LINE_SIZE 0x256
+#define OSM_REPORT_BUF_THRESHOLD (OSM_REPORT_BUF_SIZE / OSM_REPORT_LINE_SIZE)
+
+
+/****d* OpenSM: Base/osm_sm_signal_t
+* NAME
+* osm_sm_signal_t
+*
+* DESCRIPTION
+* Enumerates the possible signals used by the OSM_SM_MGR
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_signal
+{
+ OSM_SM_SIGNAL_INIT = 0,
+ OSM_SM_SIGNAL_DISCOVERY_COMPLETED,
+ OSM_SM_SIGNAL_POLLING_TIMEOUT,
+ OSM_SM_SIGNAL_DISCOVER,
+ OSM_SM_SIGNAL_DISABLE,
+ OSM_SM_SIGNAL_HANDOVER,
+ OSM_SM_SIGNAL_HANDOVER_SENT,
+ OSM_SM_SIGNAL_ACKNOWLEDGE,
+ OSM_SM_SIGNAL_STANDBY,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,
+ OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,
+ OSM_SM_SIGNAL_MAX
+
+} osm_sm_signal_t;
+/***********/
+
+/****d* OpenSM/osm_mcast_req_type_t
+* NAME
+* osm_mcast_req_type_t
+*
+* DESCRIPTION
+* Enumerates the possible signals used by the OSM_MCAST_REQUEST
+*
+* SYNOPSIS
+*/
+typedef enum _osm_mcast_req_type
+{
+ OSM_MCAST_REQ_TYPE_CREATE,
+ OSM_MCAST_REQ_TYPE_JOIN,
+ OSM_MCAST_REQ_TYPE_LEAVE,
+ OSM_MCAST_REQ_TYPE_SUBNET_CHANGE
+
+} osm_mcast_req_type_t;
+/***********/
+
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH
+* NAME
+* MAX_UPDN_GUID_FILE_LINE_LENGTH
+*
+* DESCRIPTION
+* The maximum line number when reading updn guid file
+*
+* SYNOPSIS
+*/
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120
+/**********/
+
+END_C_DECLS
+
+#endif /* _OSM_BASE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 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.
+ *
+ * $Id: osm_base.h 3401 2005-09-13 12:58:45Z halr $
+ */
+
+
+/*
+ * Abstract:
+ * Basic OpenSM definitions and structures.
+ * This object represents an OpenSM "base class".
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#ifndef _OSM_BASE_H_
+#define _OSM_BASE_H_
+
+#ifdef __WIN__
+#include <vendor/winosm_common.h>
+#define OSM_CDECL __cdecl
+#else
+#define OSM_CDECL
+#endif
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Constants
+* NAME
+* Constants
+*
+* DESCRIPTION
+* The following constants are used throughout the OpenSM.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****h* OpenSM/Base
+* NAME
+* Base
+*
+* DESCRIPTION
+* The Base object encapsulates basic information needed by the
+* OpenSM to manage objects. Each OpenSM object includes the
+* Base object as the first member.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+* OSM_VERSION
+*
+* DESCRIPTION
+* The version String for OpenSM
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-1.1.0"
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY
+* NAME
+* OSM_DEFAULT_M_KEY
+*
+* DESCRIPTION
+* Managment key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_M_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY
+* NAME
+* OSM_DEFAULT_SM_KEY
+*
+* DESCRIPTION
+* Subnet Manager key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_LMC
+* NAME
+* OSM_DEFAULT_LMC
+*
+* DESCRIPTION
+* Default LMC value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LMC 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS
+* NAME
+* OSM_DEFAULT_MAX_OP_VLS
+*
+* DESCRIPTION
+* Default Maximal Operational VLs to be initialized on
+* the link ports PortInfo by the OpenSM.
+* Default value provides backward compatibility.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MAX_OP_VLS 5
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SL
+* NAME
+* OSM_DEFAULT_SL
+*
+* DESCRIPTION
+* Default SL value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SL 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY
+* NAME
+* OSM_DEFAULT_SM_PRIORITY
+*
+* DESCRIPTION
+* Default SM priority value used by the OpenSM,
+* as defined in the SMInfo attribute. 0 is the highest priority.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_PRIORITY 0
+/********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR
+* NAME
+* OSM_DEFAULT_TMP_DIR
+*
+* DESCRIPTION
+* Specifies the default temporary directory for the log file, subnet.lst
+* and the other log files (with the exception of osm.log for Linux being
+* in /var/log).
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_TMP_DIR "C:\\Windows\\Temp\\"
+#else
+#define OSM_DEFAULT_TMP_DIR "/tmp/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR
+* NAME
+* OSM_DEFAULT_CACHE_DIR
+*
+* DESCRIPTION
+* Specifies the default cache directory for the db files.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CACHE_DIR "C:\\Windows\\Temp\\"
+#else
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE
+* NAME
+* OSM_DEFAULT_LOG_FILE
+*
+* DESCRIPTION
+* Specifies the default log file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_LOG_FILE "C:\\Windows\\Temp\\osm.log"
+#else
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
+* NAME
+* OSM_DEFAULT_SWEEP_INTERVAL_SECS
+*
+* DESCRIPTION
+* Specifies the default number of seconds between subnet sweeps.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+* NAME
+* OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+*
+* DESCRIPTION
+* Specifies the default transaction timeout in milliseconds.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 100
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT
+* NAME
+* OSM_DEFAULT_SUBNET_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default transaction timeout.
+* timeout time = 4us * 2^timeout.
+* We use here ~1sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE
+* NAME
+* OSM_DEFAULT_SWITCH_PACKET_LIFE
+*
+* DESCRIPTION
+* Specifies the default max life time for a pcket on the switch.
+* timeout time = 4us * 2^timeout.
+* We use here the value of ~1sec
+* A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+* NAME
+* OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+* Sets the time a packet can live in the head of the VL Queue
+* We use here the value of ~1sec
+* A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+* NAME
+* OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+* Sets the time a packet can live in the head of the VL Queue
+* of a port that drives a CA port.
+* We use here the value of ~130usec
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT
+* NAME
+* OSM_DEFAULT_LEAF_VL_STALL_COUNT
+*
+* DESCRIPTION
+* Sets the number of contigious head of queue life time drops that
+* puts the VL into stalled state. In stalled state the port supposed to
+* drop everything for 8*(head of queue lifetime)
+* We use here the value of 1 - so any drop due to HOQ means stalling the VL
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+* NAME
+* OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default timeout for ignoring same trap.
+* timeout time = 5000000us
+* We use here ~5sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT
+* NAME
+* OSM_DEFAULT_UNHEALTHY_TIMEOUT
+*
+* DESCRIPTION
+* Specifies the default timeout for setting port as un-healthy.
+* timeout time = 60000000us
+* We use here ~60sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD
+* NAME
+* OSM_DEFAULT_ERROR_THRESHOLD
+*
+* DESCRIPTION
+* Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE
+* NAME
+* OSM_DEFAULT_SMP_MAX_ON_WIRE
+*
+* DESCRIPTION
+* Specifies the default number of VL15 SMP MADs allowed on
+* the wire at any one time.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 1
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP0_RCV_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP0 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP0_SEND_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP0 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE
+* NAME
+* OSM_SM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+* Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256
+
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+* NAME
+* OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+*
+* DESCRIPTION
+* Specifies the polling timeout (in miliseconds) - the timeout
+* between one poll to another.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000
+/**********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+* NAME
+* OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+*
+* DESCRIPTION
+* Specifies the number of polling retries before the SM goes back
+* to DISCOVERY stage. So the total time for handoff is 3min.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 18
+/**********/
+
+/****d* OpenSM: Base/OSM_NO_PATH
+* NAME
+* OSM_NO_PATH
+*
+* DESCRIPTION
+* Value indicating there is no path to the given LID.
+*
+* SYNOPSIS
+*/
+#define OSM_NO_PATH 0xFF
+/**********/
+
+/****d* OpenSM: Base/osm_thread_state_t
+* NAME
+* osm_thread_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of worker threads, such
+* as the subnet sweeper.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_thread_state
+{
+ OSM_THREAD_STATE_NONE = 0,
+ OSM_THREAD_STATE_INIT,
+ OSM_THREAD_STATE_RUN,
+ OSM_THREAD_STATE_EXIT
+
+} osm_thread_state_t;
+/***********/
+
+/*
+ * OSM_CAP ARE C15-0.1.7 Table 152
+ */
+
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP
+* Name
+* OSM_CAP_IS_SUBN_OPT_RECS_SUP
+*
+* DESCRIPTION
+* Support all optional attributes not including:
+* MCMemberRecord, TraceRecord, MultPiathRecord
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP
+* Name
+* OSM_CAP_IS_UD_MCAST_SUP
+*
+* DESCRIPTION
+* Multicast is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_MULTI_PATH_SUP
+* Name
+* OSM_CAP_IS_MULTI_PATH_SUP
+*
+* DESCRIPTION
+* Multi Path is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_MULTI_PATH_SUP (1 << 10);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP
+* Name
+* OSM_CAP_IS_REINIT_SUP
+*
+* DESCRIPTION
+* SM/SA supports re-initialization supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_REINIT_SUP (1 << 11);
+/***********/
+
+/****d* OpenSM: Base/osm_sm_state_t
+* NAME
+* osm_sm_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of the SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_state
+{
+ OSM_SM_STATE_NO_STATE = 0,
+ OSM_SM_STATE_INIT,
+ OSM_SM_STATE_IDLE,
+ OSM_SM_STATE_SWEEP_LIGHT,
+ OSM_SM_STATE_SWEEP_LIGHT_WAIT,
+ OSM_SM_STATE_SWEEP_HEAVY_SELF,
+ OSM_SM_STATE_SWEEP_HEAVY_SUBNET,
+ OSM_SM_STATE_SET_SM_UCAST_LID,
+ OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,
+ OSM_SM_STATE_SET_SM_UCAST_LID_DONE,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,
+ OSM_SM_STATE_SET_UCAST_TABLES,
+ OSM_SM_STATE_SET_UCAST_TABLES_WAIT,
+ OSM_SM_STATE_SET_UCAST_TABLES_DONE,
+ OSM_SM_STATE_SET_MCAST_TABLES,
+ OSM_SM_STATE_SET_MCAST_TABLES_WAIT,
+ OSM_SM_STATE_SET_MCAST_TABLES_DONE,
+ OSM_SM_STATE_SET_LINK_PORTS,
+ OSM_SM_STATE_SET_LINK_PORTS_WAIT,
+ OSM_SM_STATE_SET_LINK_PORTS_DONE,
+ OSM_SM_STATE_SET_ARMED,
+ OSM_SM_STATE_SET_ARMED_WAIT,
+ OSM_SM_STATE_SET_ARMED_DONE,
+ OSM_SM_STATE_SET_ACTIVE,
+ OSM_SM_STATE_SET_ACTIVE_WAIT,
+ OSM_SM_STATE_LOST_NEGOTIATION,
+ OSM_SM_STATE_STANDBY,
+ OSM_SM_STATE_SUBNET_UP,
+ OSM_SM_STATE_PROCESS_REQUEST,
+ OSM_SM_STATE_PROCESS_REQUEST_WAIT,
+ OSM_SM_STATE_PROCESS_REQUEST_DONE,
+ OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,
+ OSM_SM_STATE_MAX
+
+} osm_sm_state_t;
+/***********/
+
+/****d* OpenSM: Base/osm_signal_t
+* NAME
+* osm_signal_t
+*
+* DESCRIPTION
+* Enumerates the possible signal codes used by the OSM managers
+* This cannot be an enum type, since conversion to and from
+* integral types is necessary when passing signals through
+* the dispatcher.
+*
+* SYNOPSIS
+*/
+#define OSM_SIGNAL_NONE 0
+#define OSM_SIGNAL_SWEEP 1
+#define OSM_SIGNAL_CHANGE_DETECTED 2
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS 3
+#define OSM_SIGNAL_DONE 4
+#define OSM_SIGNAL_DONE_PENDING 5
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION 6
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL 7
+#define OSM_SIGNAL_IDLE_TIME_PROCESS 8
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST 9
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED 10
+#define OSM_SIGNAL_EXIT_STBY 11
+#define OSM_SIGNAL_MAX 12
+
+typedef uintn_t osm_signal_t;
+/***********/
+
+/****d* OpenSM: Base/osm_state_mgr_mode_t
+* NAME
+* osm_state_mgr_mode_t
+*
+* DESCRIPTION
+* Enumerates the possible state progressing codes used by the OSM
+* state manager.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_state_mgr_mode
+{
+ OSM_STATE_STEP_CONTINUOUS = 0,
+ OSM_STATE_STEP_TAKE_ONE,
+ OSM_STATE_STEP_BREAK
+} osm_state_mgr_mode_t;
+/*
+* OSM_STATE_STEP_CONTINUOUS
+* normal automatic progress mode
+*
+* OSM_STATE_STEP_TAKE_ONE
+* Do one step
+*
+* OSM_STATE_STEP_BREAK
+* Stop before taking next step (the while loop in the state
+* manager automatically change to this state).
+*
+**********/
+
+#define OSM_REPORT_BUF_SIZE 0x10000
+#define OSM_REPORT_LINE_SIZE 0x256
+#define OSM_REPORT_BUF_THRESHOLD (OSM_REPORT_BUF_SIZE / OSM_REPORT_LINE_SIZE)
+
+
+/****d* OpenSM: Base/osm_sm_signal_t
+* NAME
+* osm_sm_signal_t
+*
+* DESCRIPTION
+* Enumerates the possible signals used by the OSM_SM_MGR
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_signal
+{
+ OSM_SM_SIGNAL_INIT = 0,
+ OSM_SM_SIGNAL_DISCOVERY_COMPLETED,
+ OSM_SM_SIGNAL_POLLING_TIMEOUT,
+ OSM_SM_SIGNAL_DISCOVER,
+ OSM_SM_SIGNAL_DISABLE,
+ OSM_SM_SIGNAL_HANDOVER,
+ OSM_SM_SIGNAL_HANDOVER_SENT,
+ OSM_SM_SIGNAL_ACKNOWLEDGE,
+ OSM_SM_SIGNAL_STANDBY,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,
+ OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,
+ OSM_SM_SIGNAL_MAX
+
+} osm_sm_signal_t;
+/***********/
+
+/****d* OpenSM/osm_mcast_req_type_t
+* NAME
+* osm_mcast_req_type_t
+*
+* DESCRIPTION
+* Enumerates the possible signals used by the OSM_MCAST_REQUEST
+*
+* SYNOPSIS
+*/
+typedef enum _osm_mcast_req_type
+{
+ OSM_MCAST_REQ_TYPE_CREATE,
+ OSM_MCAST_REQ_TYPE_JOIN,
+ OSM_MCAST_REQ_TYPE_LEAVE,
+ OSM_MCAST_REQ_TYPE_SUBNET_CHANGE
+
+} osm_mcast_req_type_t;
+/***********/
+
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH
+* NAME
+* MAX_UPDN_GUID_FILE_LINE_LENGTH
+*
+* DESCRIPTION
+* The maximum line number when reading updn guid file
+*
+* SYNOPSIS
+*/
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120
+/**********/
+
+END_C_DECLS
+
+#endif /* _OSM_BASE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_DB_H_
+#define _OSM_DB_H_
+
+
+/*
+ * Abstract:
+ * Declaration of the DB interface.
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <complib/cl_list.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Database
+* NAME
+* Database
+*
+* DESCRIPTION
+* The OpenSM database interface provide the means to restore persistat
+* data, query, modify, delete and evemtually commit it back to the
+* persistant media.
+*
+* The interface is defined such that it can is not "data dependant":
+* All keys and data items are texts.
+*
+* The DB implementation should be thread safe, thus callers do not need to
+* provide serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Database/osm_db_domain_t
+* NAME
+* osm_db_domain_t
+*
+* DESCRIPTION
+* A domain of the database. Can be viewed as a database table.
+*
+* The osm_db_domain_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db_domain {
+ struct _osm_db *p_db;
+ void *p_domain_imp;
+} osm_db_domain_t;
+/*
+* FIELDS
+* p_db
+* Pointer to the parent database object.
+*
+* p_domain_imp
+* Pointer to the db implementation object
+*
+* SEE ALSO
+* osm_db_t
+*********/
+
+/****s* OpenSM: Database/osm_db_t
+* NAME
+* osm_db_t
+*
+* DESCRIPTION
+* The main database object.
+*
+* The osm_db_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db
+{
+ void *p_db_imp;
+ osm_log_t *p_log;
+ cl_list_t domains;
+} osm_db_t;
+/*
+* FIELDS
+* p_db_imp
+* Pointer to the database implementation object
+*
+* p_log
+* Pointer to the OSM logging facility
+*
+* domains
+* List of initialize domains
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Database/osm_db_construct
+* NAME
+* osm_db_construct
+*
+* DESCRIPTION
+* Construct a database.
+*
+* SYNOPSIS
+*/
+void
+osm_db_construct(
+ IN osm_db_t* const p_db );
+/*
+* PARAMETERS
+* p_db
+* [in] Pointer to the database object to custruct
+*
+* RETURN VALUES
+* NONE
+*
+* SEE ALSO
+* Database, osm_db_init, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_destroy
+* NAME
+* osm_db_destroy
+*
+* DESCRIPTION
+* Destroys the osm_db_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_db_destroy(
+ IN osm_db_t* const p_db );
+/*
+* PARAMETERS
+* p_db
+* [in] Pointer to osm_db_t structure to destroy
+*
+* SEE ALSO
+* Database, osm_db_construct, osm_db_init
+*********/
+
+/****f* OpenSM: Database/osm_db_init
+* NAME
+* osm_db_init
+*
+* DESCRIPTION
+* Initializes the osm_db_t structure.
+*
+* SYNOPSIS
+*/
+int
+osm_db_init(
+ IN osm_db_t* const p_db,
+ IN osm_log_t *p_log );
+/*
+* PARAMETERS
+*
+* p_db
+* [in] Pointer to the database object to initialize
+*
+* p_log
+* [in] Pointer to the OSM logging facility
+*
+* RETURN VALUES
+* 0 on success 1 otherwise
+*
+* SEE ALSO
+* Database, osm_db_construct, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_domain_init
+* NAME
+* osm_db_domain_init
+*
+* DESCRIPTION
+* Initializes the osm_db_domain_t structure.
+*
+* SYNOPSIS
+*/
+osm_db_domain_t*
+osm_db_domain_init(
+ IN osm_db_t* const p_db,
+ IN char *domain_name);
+/*
+* PARAMETERS
+*
+* p_db
+* [in] Pointer to the database object to initialize
+*
+* domain_name
+* [in] a char array with the domain name.
+*
+* RETURN VALUES
+* pointer to the new domain object or NULL if failed.
+*
+* SEE ALSO
+* Database, osm_db_construct, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_restore
+* NAME
+* osm_db_restore
+*
+* DESCRIPTION
+* Reads the entire domain from persistant storage - overrides all
+* existing cached data (if any).
+*
+* SYNOPSIS
+*/
+int
+osm_db_restore(
+ IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object to restore from persistant db
+*
+* RETURN VALUES
+* 0 if successful 1 otherwize
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_clear, osm_db_store,
+* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_clear
+* NAME
+* osm_db_clear
+*
+* DESCRIPTION
+* Clears the entire domain values from/in the cache
+*
+* SYNOPSIS
+*/
+int
+osm_db_clear(
+ IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object to clear
+*
+* RETURN VALUES
+* 0 if successful 1 otherwize
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_store,
+* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_store
+* NAME
+* osm_db_store
+*
+* DESCRIPTION
+* Store the domain cache back to the database (commit)
+*
+* SYNOPSIS
+*/
+int osm_db_store(
+ IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object to restore from persistant db
+*
+* RETURN VALUES
+* 0 if successful 1 otherwize
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_clear,
+* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_keys
+* NAME
+* osm_db_keys
+*
+* DESCRIPTION
+* Retrive all keys of the domain
+*
+* SYNOPSIS
+*/
+int
+osm_db_keys(
+ IN osm_db_domain_t *p_domain,
+ OUT cl_list_t* p_key_list);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object
+*
+* p_key_list
+* [out] List of key values. It should be PRE constructed and initialized.
+*
+* RETURN VALUES
+* 0 if successful 1 otherwize
+*
+* NOTE: the caller needs to free and destruct the list,
+* the keys returned are intrnal to the hash and should NOT be free'ed
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store,
+* osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_lookup
+* NAME
+* osm_db_lookup
+*
+* DESCRIPTION
+* Lookup an entry in the domain by the given key
+*
+* SYNOPSIS
+*/
+/* lookup value by key */
+char *osm_db_lookup(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object
+*
+* key
+* [in] The key to look for
+*
+* RETURN VALUES
+* the value as char * or NULL if not found
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store,
+* osm_db_keys, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_update
+* NAME
+* osm_db_update
+*
+* DESCRIPTION
+* Set the value of the given key
+*
+* SYNOPSIS
+*/
+int
+osm_db_update(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key,
+ IN char *const p_val);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object
+*
+* p_key
+* [in] The key to update
+*
+* p_val
+* [in] The value to update
+*
+* RETURN VALUES
+* 0 on success
+*
+* NOTE: the value will be duplicated so can be free'ed
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store,
+* osm_db_keys, osm_db_lookup, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_delete
+* NAME
+* osm_db_delete
+*
+* DESCRIPTION
+* Delete an entry by the given key
+*
+* SYNOPSIS
+*/
+int
+osm_db_delete(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key);
+/*
+* PARAMETERS
+*
+* p_domain
+* [in] Pointer to the database domain object
+*
+* p_key
+* [in] The key to look for
+*
+* RETURN VALUES
+* 0 on success
+*
+* SEE ALSO
+* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store,
+* osm_db_keys, osm_db_lookup, osm_db_update
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DB_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/****h* OpenSM/DB-Pack
+* NAME
+* Database Types
+*
+* DESCRIPTION
+* This module provides packing and unpacking of the database
+* storage into specific types.
+*
+* The following domains/conversions are supported:
+* guid2lid - key is a guid and data is a lid.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+#ifndef _OSM_DB_PACK_H_
+#define _OSM_DB_PACK_H_
+
+#include <opensm/osm_db.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_init
+* NAME
+* osm_db_guid2lid_init
+*
+* DESCRIPTION
+* Initialize a domain for the guid2lid table
+*
+* SYNOPSIS
+*/
+static inline osm_db_domain_t*
+osm_db_guid2lid_init(
+ IN osm_db_t* const p_db )
+{
+ return( osm_db_domain_init( p_db, "guid2lid" ) );
+}
+/*
+* PARAMETERS
+* p_db
+* [in] Pointer to the database object to construct
+*
+* RETURN VALUES
+* The pointer to the new allocated domain object or NULL.
+*
+* NOTE: DB domains are destroyed by the osm_db_destroy
+*
+* SEE ALSO
+* Database, osm_db_init, osm_db_destroy
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_init
+* NAME
+* osm_db_guid2lid_init
+*
+* DESCRIPTION
+* Initialize a domain for the guid2lid table
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db_guid_elem {
+ cl_list_item_t item;
+ uint64_t guid;
+} osm_db_guid_elem_t;
+/*
+* FIELDS
+* item
+* required for list manipulations
+*
+* guid
+*
+************/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_guids
+* NAME
+* osm_db_guid2lid_guids
+*
+* DESCRIPTION
+* Provides back a list of guid elements.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_guids(
+ IN osm_db_domain_t* const p_g2l,
+ OUT cl_qlist_t* p_guid_list );
+/*
+* PARAMETERS
+* p_g2l
+* [in] Pointer to the guid2lid domain
+*
+* p_guid_list
+* [out] A quick list of guid elements of type osm_db_guid_elem_t
+*
+* RETURN VALUES
+* 0 if successful
+*
+* NOTE: the output qlist should be initialized and each item freed
+* by the caller, then destroyed.
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids, osm_db_guid2lid_get
+* osm_db_guid2lid_set, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_get
+* NAME
+* osm_db_guid2lid_get
+*
+* DESCRIPTION
+* Get a lid range by given guid.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_get(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid,
+ OUT uint16_t *p_min_lid,
+ OUT uint16_t *p_max_lid);
+/*
+* PARAMETERS
+* p_g2l
+* [in] Pointer to the guid2lid domain
+*
+* guid
+* [in] The guid to look for
+*
+* p_min_lid
+* [out] Pointer to the resulting min lid in host order.
+*
+* p_max_lid
+* [out] Pointer to the resulting max lid in host order.
+*
+* RETURN VALUES
+* 0 if successful. The lid will be set to 0 if not found.
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids
+* osm_db_guid2lid_set, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_set
+* NAME
+* osm_db_guid2lid_set
+*
+* DESCRIPTION
+* Set a lid range for the given guid.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_set(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid,
+ IN uint16_t min_lid,
+ IN uint16_t max_lid);
+/*
+* PARAMETERS
+* p_g2l
+* [in] Pointer to the guid2lid domain
+*
+* guid
+* [in] The guid to look for
+*
+* min_lid
+* [in] The min lid value to set
+*
+* max_lid
+* [in] The max lid value to set
+*
+* RETURN VALUES
+* 0 if successful
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids
+* osm_db_guid2lid_get, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_delete
+* NAME
+* osm_db_guid2lid_delete
+*
+* DESCRIPTION
+* Delete the entry by the given guid
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_delete(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid );
+/*
+* PARAMETERS
+* p_g2l
+* [in] Pointer to the guid2lid domain
+*
+* guid
+* [in] The guid to look for
+*
+* RETURN VALUES
+* 0 if successful otherwise 1
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids
+* osm_db_guid2lid_get, osm_db_guid2lid_set
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DB_PACK_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_DROP_MGR_H_
+#define _OSM_DROP_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Drop Manager
+* NAME
+* Drop Manager
+*
+* DESCRIPTION
+* The Drop Manager object encapsulates the information
+* needed to receive the SwitchInfo attribute from a node.
+*
+* The Drop Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Drop Manager/osm_drop_mgr_t
+* NAME
+* osm_drop_mgr_t
+*
+* DESCRIPTION
+* Drop Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_drop_mgr
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_req_t *p_req;
+ cl_plock_t *p_lock;
+
+} osm_drop_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_req
+* Pointer to the Request object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Drop Manager object
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_construct
+* NAME
+* osm_drop_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Drop Manager object.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_construct(
+ IN osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Drop Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_drop_mgr_init, osm_drop_mgr_destroy
+*
+* Calling osm_drop_mgr_construct is a prerequisite to calling any other
+* method except osm_drop_mgr_init.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_init,
+* osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_destroy
+* NAME
+* osm_drop_mgr_destroy
+*
+* DESCRIPTION
+* The osm_drop_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_destroy(
+ IN osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Drop Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_drop_mgr_construct or osm_drop_mgr_init.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_construct,
+* osm_drop_mgr_init
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_init
+* NAME
+* osm_drop_mgr_init
+*
+* DESCRIPTION
+* The osm_drop_mgr_init function initializes a
+* Drop Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_drop_mgr_init(
+ IN osm_drop_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_drop_mgr_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Drop Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Drop Manager methods.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_construct,
+* osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_process
+* NAME
+* osm_drop_mgr_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_process(
+ IN const osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_drop_mgr_t object.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* Drop Manager, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DROP_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of error code ranges for the various OpenSM modules.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ERRORS_H_
+#define _OSM_ERRORS_H_
+
+/*
+ Generic Request Controller
+ 0100 - 01FF
+
+ Node Info Receive Controller
+ 0200 - 02FF
+
+ Generic Requester
+ 0300 - 03FF
+
+ Node Info Receiver
+ 0400 - 04FF
+
+ Node Description Receiver
+ 0500 - 05FF
+
+ Node Description Receive Controller
+ 0600 - 06FF
+
+ Port Info Receiver
+ 0700 - 07FF
+
+ Port Info Receive Controller
+ 0800 - 08FF
+
+ Mad Pool
+ 0900 - 09FF
+
+ SM
+ 1000 - 10FF
+
+ SM MAD Controller
+ 1100 - 11FF
+
+ VL15 Interface
+ 1200 - 12FF
+
+ Switch Info Receive Controller
+ 1300 - 13FF
+
+ Switch Info Receiver
+ 1400 - 14FF
+
+ State Manager
+ 1500 - 15FF
+
+ State Manager Controller
+ 1600 - 16FF
+
+ LID Manager
+ 1700 - 17FF
+
+ Link Manager
+ 1800 - 18FF
+
+ Drop Manager
+ 1900 - 19FF
+
+ Linear Fowarding Receive Controller
+ 2000 - 20FF
+
+ Linear Fowarding Receiver
+ 2100 - 21FF
+
+ Vendor Specific
+ 2200 - 22FF
+
+ SMInfo Receive Controller
+ 2300 - 23FF
+
+ SMInfo Info Receiver
+ 2400 - 24FF
+
+ Generic Responder
+ 2500 - 25FF
+
+ Linear Fowarding Receive Controller
+ 2600 - 26FF
+
+ Linear Fowarding Receiver
+ 2700 - 27FF
+
+ SA MAD controller
+ 2800 - 28FF
+
+ Node Record Controller
+ 2900 - 29FF
+
+ PortInfo Record Controller
+ 3000 - 30FF
+
+ Link Record Controller
+ 3100 - 31FF
+
+ Path Record Controller
+ 3200 - 32FF
+
+ SMInfo Record Controller
+ 3300 - 33FF
+
+ Multicast Record Controller
+ 3400 - 34FF
+
+ Unicast Manager
+ 3500 - 35FF
+
+ Multicast Manager
+ 3600 - 36FF
+
+ SA Response
+ 3700 - 37FF
+
+ Link Record Receiver
+ 3800 - 38FF
+
+ Multicast Fowarding Receive Controller
+ 3900 - 39FF
+
+ Multicast Fowarding Receiver
+ 4000 - 40FF
+
+ SMInfo Record Receiver
+ 4100 - 41FF
+
+ PortInfo Record Receiver
+ 4200 - 42FF
+
+ Service Record Receiver
+ 4300 - 43FF
+
+*/
+
+#endif /* _OSM_ERRORS_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ft_conf_ctrl_t.
+ * This object represents a controller that performs a
+ * Set(Linear/Random ForwardingTable) for the specified switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_FT_CONFIG_CTRL_H_
+#define _OSM_FT_CONFIG_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Forwarding Table Configuration Controller
+* NAME
+* Forwarding Table Configuration Controller
+*
+* DESCRIPTION
+* The Forwarding Table Configuration Controller object encapsulates the
+* information needed to Set(Linear/Random ForwardingTable) at the
+* specified switch.
+*
+* The Forwarding Table Configuration Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_t
+* NAME
+* osm_ft_conf_ctrl_t
+*
+* DESCRIPTION
+* Forwarding Table Configuration Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ft_conf_ctrl
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_ft_conf_ctrl_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* Forwarding Table Configuration Controller object
+*********/
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_construct
+* NAME
+* osm_ft_conf_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Forwarding Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_ft_conf_ctrl_construct(
+ IN osm_ft_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Forwarding Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_ft_conf_ctrl_init, osm_ft_conf_ctrl_destroy
+*
+* Calling osm_ft_conf_ctrl_construct is a prerequisite to calling any other
+* method except osm_ft_conf_ctrl_init.
+*
+* SEE ALSO
+* Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_init,
+* osm_ft_conf_ctrl_destroy
+*********/
+
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_destroy
+* NAME
+* osm_ft_conf_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_ft_conf_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_ft_conf_ctrl_destroy(
+ IN osm_ft_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Forwarding Table Configuration Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ft_conf_ctrl_construct or osm_ft_conf_ctrl_init.
+*
+* SEE ALSO
+* Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_construct,
+* osm_ft_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_init
+* NAME
+* osm_ft_conf_ctrl_init
+*
+* DESCRIPTION
+* The osm_ft_conf_ctrl_init function initializes a
+* Forwarding Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_ft_conf_ctrl_init(
+ IN osm_ft_conf_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ft_conf_ctrl_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Forwarding Table Configuration Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Forwarding Table Configuration Controller methods.
+*
+* SEE ALSO
+* Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_construct,
+* osm_ft_conf_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_FT_CONFIG_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_fwd_tbl_t.
+ * This object represents a unicast forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_FWD_TBL_H_
+#define _OSM_FWD_TBL_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_rand_fwd_tbl.h>
+#include <opensm/osm_lin_fwd_tbl.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Forwarding Table
+* NAME
+* Forwarding Table
+*
+* DESCRIPTION
+* The Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage forwarding tables. The OpenSM
+* allocates one Forwarding Table object per switch in the
+* IBA subnet.
+*
+* The Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_fwd_tbl_t
+* NAME
+* osm_fwd_tbl_t
+*
+* DESCRIPTION
+* Forwarding Table structure. This object hides the type
+* of fowarding table (linear or random) actually used by
+* the switch.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_fwd_tbl_t
+{
+ osm_rand_fwd_tbl_t *p_rnd_tbl;
+ osm_lin_fwd_tbl_t *p_lin_tbl;
+
+} osm_fwd_tbl_t;
+/*
+* FIELDS
+* p_rnd_tbl
+* Pointer to the switch's Random Forwarding Table object.
+* If the switch does not use a Random Forwarding Table,
+* then this pointer is NULL.
+*
+* p_lin_tbl
+* Pointer to the switch's Linear Forwarding Table object.
+* If the switch does not use a Linear Forwarding Table,
+* then this pointer is NULL.
+*
+* SEE ALSO
+* Forwarding Table object, Random Fowarding Table object.
+*********/
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_init
+* NAME
+* osm_fwd_tbl_init
+*
+* DESCRIPTION
+* Initializes a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_fwd_tbl_init(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const ib_switch_info_t* const p_si );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* p_si
+* [in] Pointer to the SwitchInfo attribute of the associated
+* switch.
+*
+* RETURN VALUE
+* IB_SUCCESS if the operation is successful.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_destroy
+* NAME
+* osm_fwd_tbl_destroy
+*
+* DESCRIPTION
+* Destroys a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_fwd_tbl_destroy(
+ IN osm_fwd_tbl_t* const p_tbl );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get
+* NAME
+* osm_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_fwd_tbl_get(
+ IN const osm_fwd_tbl_t* const p_tbl,
+ IN uint16_t const lid_ho )
+{
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get( p_tbl->p_lin_tbl, lid_ho ) );
+ else
+ return( osm_rand_fwd_tbl_get( p_tbl->p_rnd_tbl, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* lid_ho
+* [in] LID (host order) for which to find the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+* IB_INVALID_PORT_NUM if the table does not have a route for this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set
+* NAME
+* osm_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_fwd_tbl_set(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ osm_lin_fwd_tbl_set( p_tbl->p_lin_tbl, lid_ho, port );
+ else
+ osm_rand_fwd_tbl_set( p_tbl->p_rnd_tbl, lid_ho, port );
+}
+
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set_block
+* NAME
+* osm_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_fwd_tbl_set_block(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_set_block( p_tbl->p_lin_tbl,
+ p_block, block_num ) );
+ else
+ return( osm_rand_fwd_tbl_set_block( p_tbl->p_rnd_tbl,
+ p_block, block_num ) );
+}
+
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_size
+* NAME
+* osm_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_size(
+ IN const osm_fwd_tbl_t* const p_tbl )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_size( p_tbl->p_lin_tbl ) );
+ else
+ return( osm_rand_fwd_tbl_get_size( p_tbl->p_rnd_tbl ) );
+}
+
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_lids_per_block
+* NAME
+* osm_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_lids_per_block(
+ IN const osm_fwd_tbl_t* const p_tbl )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_lids_per_block( p_tbl->p_lin_tbl ) );
+ else
+ return( osm_rand_fwd_tbl_get_lids_per_block( p_tbl->p_rnd_tbl ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_max_block_id_in_use(
+ p_tbl->p_lin_tbl, lid_top_ho ) );
+ else
+ return( osm_rand_fwd_tbl_get_max_block_id_in_use(
+ p_tbl->p_rnd_tbl, lid_top_ho ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_FWD_TBL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_HELPER_H_
+#define _OSM_HELPER_H_
+
+#include <iba/ib_types.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_path.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ * Declaration of helpful functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+
+/****f* OpenSM: Helper/ib_get_sa_method_str
+ * NAME
+ * ib_get_sa_method_str
+ *
+ * DESCRIPTION
+ * Returns a string for the specified SA Method value.
+ *
+ * SYNOPSIS
+ */
+const char*
+ib_get_sa_method_str(
+ IN uint8_t method );
+/*
+ * PARAMETERS
+ * method
+ * [in] Network order METHOD ID value.
+ *
+ * RETURN VALUES
+ * Pointer to the method string.
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Helper/ib_get_sm_method_str
+* NAME
+* ib_get_sm_method_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM Method value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sm_method_str(
+ IN uint8_t method );
+/*
+* PARAMETERS
+* method
+* [in] Network order METHOD ID value.
+*
+* RETURN VALUES
+* Pointer to the method string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sm_attr_str
+* NAME
+* ib_get_sm_attr_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM attribute value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sm_attr_str(
+ IN ib_net16_t attr );
+/*
+* PARAMETERS
+* attr
+* [in] Network order attribute ID value.
+*
+* RETURN VALUES
+* Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sa_attr_str
+* NAME
+* ib_get_sa_attr_str
+*
+* DESCRIPTION
+* Returns a string for the specified SA attribute value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sa_attr_str(
+ IN ib_net16_t attr );
+/*
+* PARAMETERS
+* attr
+* [in] Network order attribute ID value.
+*
+* RETURN VALUES
+* Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_port_info
+* NAME
+* osm_dump_port_info
+*
+* DESCRIPTION
+* Dumps the PortInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void osm_dump_port_info(
+ IN osm_log_t* const p_log,
+ IN const ib_net64_t node_guid,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const ib_port_info_t* const p_pi,
+ IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the osm_log_t object
+*
+* node_guid
+* [in] Node GUID that owns this port.
+*
+* port_guid
+* [in] Port GUID for this port.
+*
+* port_num
+* [in] Port number for this port.
+*
+* p_pi
+* [in] Pointer to the PortInfo attribute
+*
+* log_level
+* [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void
+osm_dump_path_record(
+ IN osm_log_t* const p_log,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_node_record(
+ IN osm_log_t* const p_log,
+ IN const ib_node_record_t* const p_nr,
+ IN const osm_log_level_t log_level );
+
+
+void
+osm_dump_mc_record(
+ IN osm_log_t* const p_log,
+ IN const ib_member_rec_t* const p_mcmr,
+ IN const osm_log_level_t log_level );
+
+
+void
+osm_dump_link_record(
+ IN osm_log_t* const p_log,
+ IN const ib_link_record_t* const p_lr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_service_record(
+ IN osm_log_t* const p_log,
+ IN const ib_service_record_t* const p_sr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_portinfo_record(
+ IN osm_log_t* const p_log,
+ IN const ib_portinfo_record_t* const p_pir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_inform_info(
+ IN osm_log_t* const p_log,
+ IN const ib_inform_info_t* const p_ii,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_pkey_block(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint16_t block_num,
+ IN uint8_t port_num,
+ IN const ib_pkey_table_t* const p_pkey_tbl,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_slvl_map_table(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint8_t in_port_num,
+ IN uint8_t out_port_num,
+ IN const ib_slvl_table_t* const p_slvl_tbl,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_vl_arb_table(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint8_t block_num,
+ IN uint8_t port_num,
+ IN const ib_vl_arb_table_t* const p_vla_tbl,
+ IN const osm_log_level_t log_level );
+
+/****f* OpenSM: Helper/osm_dump_port_info
+* NAME
+* osm_dump_port_info
+*
+* DESCRIPTION
+* Dumps the PortInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void osm_dump_node_info(
+ IN osm_log_t* const p_log,
+ IN const ib_node_info_t* const p_ni,
+ IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the osm_log_t object
+*
+* p_ni
+* [in] Pointer to the NodeInfo attribute
+*
+* log_level
+* [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_sm_info
+* NAME
+* osm_dump_sm_info
+*
+* DESCRIPTION
+* Dumps the SMInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_sm_info(
+ IN osm_log_t* const p_log,
+ IN const ib_sm_info_t* const p_smi,
+ IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the osm_log_t object
+*
+* p_smi
+* [in] Pointer to the SMInfo attribute
+*
+* log_level
+* [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_switch_info
+* NAME
+* osm_dump_switch_info
+*
+* DESCRIPTION
+* Dumps the SwitchInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_switch_info(
+ IN osm_log_t* const p_log,
+ IN const ib_switch_info_t* const p_si,
+ IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the osm_log_t object
+*
+* p_si
+* [in] Pointer to the SwitchInfo attribute
+*
+* log_level
+* [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_notice
+* NAME
+* osm_dump_notice
+*
+* DESCRIPTION
+* Dumps the Notice attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_notice(
+ IN osm_log_t* const p_log,
+ IN const ib_mad_notice_attr_t *p_ntci,
+ IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the osm_log_t object
+*
+* p_ntci
+* [in] Pointer to the Notice attribute
+*
+* log_level
+* [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_disp_msg_str
+* NAME
+* osm_get_disp_msg_str
+*
+* DESCRIPTION
+* Returns a string for the specified Dispatcher message.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_disp_msg_str(
+ IN cl_disp_msgid_t msg );
+/*
+* PARAMETERS
+* msg
+* [in] Dispatcher message ID value.
+*
+* RETURN VALUES
+* Pointer to the message discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void osm_dump_dr_path(
+ IN osm_log_t* const p_log,
+ IN const osm_dr_path_t* const p_path,
+ IN const osm_log_level_t level );
+
+void osm_dump_smp_dr_path(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t level );
+
+void osm_dump_dr_smp(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t level );
+
+void osm_dump_sa_mad(
+ IN osm_log_t* const p_log,
+ IN const ib_sa_mad_t* const p_smp,
+ IN const osm_log_level_t level );
+
+/****f* IBA Base: Types/osm_get_sm_state_str
+* NAME
+* osm_get_sm_state_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_state_str(
+ IN osm_sm_state_t state );
+/*
+* PARAMETERS
+* state
+* [in] SM State value
+*
+* RETURN VALUES
+* Pointer to the state discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_sm_signal_str
+* NAME
+* osm_get_sm_signal_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_signal_str(
+ IN osm_signal_t signal );
+/*
+* PARAMETERS
+* state
+* [in] Signal value
+*
+* RETURN VALUES
+* Pointer to the signal discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+const char*
+osm_get_port_state_str_fixed_width(
+ IN uint8_t port_state );
+
+const char*
+osm_get_node_type_str_fixed_width(
+ IN uint32_t node_type );
+
+const char*
+osm_get_manufacturer_str(
+ IN uint64_t const guid_ho );
+
+const char*
+osm_get_mtu_str(
+ IN uint8_t const mtu );
+
+const char*
+osm_get_lwa_str(
+ IN uint8_t const lwa );
+
+const char*
+osm_get_mtu_str(
+ IN uint8_t const mtu );
+
+const char*
+osm_get_lwa_str(
+ IN uint8_t const lwa );
+
+const char*
+osm_get_lsa_str(
+ IN uint8_t const lsa );
+
+
+/****f* IBA Base: Types/osm_get_sm_mgr_signal_str
+* NAME
+* osm_get_sm_mgr_signal_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM manager signal.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_mgr_signal_str(
+ IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+* signal
+* [in] SM manager signal
+*
+* RETURN VALUES
+* Pointer to the signal discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_sm_mgr_state_str
+* NAME
+* osm_get_sm_mgr_state_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM manager state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_mgr_state_str(
+ IN uint16_t state );
+/*
+* PARAMETERS
+* state
+* [in] SM manager state
+*
+* RETURN VALUES
+* Pointer to the state discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_HELPER_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_inform_rec_t.
+ * This object represents an IBA Inform Record.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * Author:
+ * Eitan Zahavi, Mellanox
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_INFR_H_
+#define _OSM_INFR_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_trap_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Inform Record
+* NAME
+* Inform Record
+*
+* DESCRIPTION
+* The Inform record encapsulates the information needed by the
+* SA to manage InformInfo registrations and sending Reports(Notice)
+* when SM receives Traps for registered LIDs.
+*
+* The inform records is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: Inform Record/osm_infr_t
+* NAME
+* osm_infr_t
+*
+* DESCRIPTION
+* Inform Record structure.
+*
+* The osm_infr_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_t
+{
+ cl_list_item_t list_item;
+ osm_bind_handle_t h_bind; // a handle of lower level mad srvc
+ osm_infr_rcv_t* p_infr_rcv; // the receiver of inform_info's
+ osm_mad_addr_t report_addr;
+ ib_inform_info_record_t inform_record;
+} osm_infr_t;
+/*
+* FIELDS
+* list_item
+* List Item for qlist linkage. Must be first element!!
+*
+* inform_record
+* The Inform Info Record
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_new
+* NAME
+* osm_infr_new
+*
+* DESCRIPTION
+* Allocates and initializes a Inform Record for use.
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_new(
+ IN const osm_infr_t *p_infr_rec );
+/*
+* PARAMETERS
+* p_inf_rec
+* [in] Pointer to IB Inform Record
+*
+* RETURN VALUES
+* pointer to osm_infr_t structure.
+*
+* NOTES
+* Allows calling other service record methods.
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+
+/****f* OpenSM: Inform Record/osm_infr_init
+* NAME
+* osm_infr_new
+*
+* DESCRIPTION
+* Initializes the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_init(
+ IN osm_infr_t* const p_infr,
+ IN const osm_infr_t *p_infr_rec );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+* p_inf_rec
+* [in] Pointer to the ib_inform_info_record_t
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_construct
+* NAME
+* osm_infr_construct
+*
+* DESCRIPTION
+* Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_construct(
+ IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_destroy
+* NAME
+* osm_infr_destroy
+*
+* DESCRIPTION
+* Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_destroy(
+ IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_get_by_rid
+* NAME
+* osm_infr_get_by_rid
+*
+* DESCRIPTION
+* Find a matching osm_infr_t in the subnet DB by inform_info_record RID
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_rid(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN ib_inform_info_record_t* const p_inf_rec );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the subnet object
+*
+* p_log
+* [in] Pointer to the log object
+*
+* p_inf_rec
+* [in] Pointer to an inform_info record with the search RID
+*
+* RETURN
+* The matching osm_infr_t
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_get_by_rec
+* NAME
+* osm_infr_get_by_rec
+*
+* DESCRIPTION
+* Find a matching osm_infr_t in the subnet DB by inform_info_record
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_rec(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t* const p_infr_rec );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the subnet object
+*
+* p_log
+* [in] Pointer to the log object
+*
+* p_inf_rec
+* [in] Pointer to an inform_info record
+*
+* RETURN
+* The matching osm_infr_t
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+void
+osm_infr_insert_to_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t *p_infr);
+
+void
+osm_infr_remove_from_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t *p_infr);
+
+/****f* OpenSM: Inform Record/osm_report_notice
+* NAME
+* osm_report_notice
+*
+* DESCRIPTION
+* Once a Trap was received by the osm_trap_rcv, or a Trap sourced in
+* the SM was sent (Traps 64-67) this routine is called with a copy of
+* the notice data.
+* Given a notice attribute - compare and see if it matches the InformInfo
+* Element and if it does - call the Report(Notice) for the
+* target QP registered by the address stored in the InformInfo element
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_report_notice(
+ IN osm_log_t* const p_log,
+ IN osm_subn_t* p_subn,
+ IN ib_mad_notice_attr_t *p_ntc);
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the trap receiver
+*
+* p_ntc
+* [in] Pointer to a copy of the incoming trap notice attribute.
+*
+* RETURN
+* IB_SUCCESS on good completion
+*
+* SEE ALSO
+* Inform Record, osm_trap_rcv
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_INFR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lid_mgr_t.
+ * This object represents the LID Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LID_MGR_H_
+#define _OSM_LID_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_LID_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/LID Manager
+* NAME
+* LID Manager
+*
+* DESCRIPTION
+* The LID Manager object encapsulates the information
+* needed to control LID assignments on the subnet.
+*
+* The LID Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: LID Manager/osm_lid_mgr_t
+* NAME
+* osm_lid_mgr_t
+*
+* DESCRIPTION
+* LID Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lid_mgr
+{
+ osm_subn_t *p_subn;
+ osm_db_t *p_db;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ boolean_t send_set_reqs;
+ osm_db_domain_t *p_g2l;
+ cl_ptr_vector_t used_lids;
+ cl_qlist_t free_ranges;
+} osm_lid_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_db
+* Pointer to the database (persistency) object
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_g2l
+* Pointer to the database domain storing guid to lid mapping.
+*
+* used_lids
+* A vector the maps from the lid to its guid. keeps track of
+* existing and non existing mapping of guid->lid
+*
+* free_ranges
+* A list of available free lid ranges. The list is initialized
+* by the code that initializes the lid assignment and is consumed by the
+* procedure that finds a free range. It holds elements of type
+* osm_lid_mgr_range_t
+*
+* SEE ALSO
+* LID Manager object
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_construct
+* NAME
+* osm_lid_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a LID Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_mgr_construct(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a LID Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_lid_mgr_destroy
+*
+* Calling osm_lid_mgr_construct is a prerequisite to calling any other
+* method except osm_lid_mgr_init.
+*
+* SEE ALSO
+* LID Manager object, osm_lid_mgr_init,
+* osm_lid_mgr_destroy
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_destroy
+* NAME
+* osm_lid_mgr_destroy
+*
+* DESCRIPTION
+* The osm_lid_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_mgr_destroy(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* LID Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lid_mgr_construct or osm_lid_mgr_init.
+*
+* SEE ALSO
+* LID Manager object, osm_lid_mgr_construct,
+* osm_lid_mgr_init
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_init
+* NAME
+* osm_lid_mgr_init
+*
+* DESCRIPTION
+* The osm_lid_mgr_init function initializes a
+* LID Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lid_mgr_init(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LID Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other LID Manager methods.
+*
+* SEE ALSO
+* LID Manager object, osm_lid_mgr_construct,
+* osm_lid_mgr_destroy
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_process_sm
+* NAME
+* osm_lid_mgr_process_sm
+*
+* DESCRIPTION
+* Configures the SM's port with its designated LID values.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_lid_mgr_process_sm(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+* LID Manager
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_process_subnet
+* NAME
+* osm_lid_mgr_process_subnet
+*
+* DESCRIPTION
+* Configures subnet ports (except the SM port itself) with their
+* designated LID values.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+* LID Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LID_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lft_rcv_t.
+ * This object represents the LFT Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LFT_RCV_H_
+#define _OSM_LFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LFT Receiver
+* NAME
+* LFT Receiver
+*
+* DESCRIPTION
+* The LFT Receiver object encapsulates the information
+* needed to receive the LFT attribute from a node.
+*
+* The LFT Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: LFT Receiver/osm_lft_rcv_t
+* NAME
+* osm_lft_rcv_t
+*
+* DESCRIPTION
+* LFT Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_lft_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* LFT Receiver object
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_construct
+* NAME
+* osm_lft_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a LFT Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_construct(
+ IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a LFT Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lft_rcv_init, osm_lft_rcv_destroy
+*
+* Calling osm_lft_rcv_construct is a prerequisite to calling any other
+* method except osm_lft_rcv_init.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_init,
+* osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_destroy
+* NAME
+* osm_lft_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lft_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_destroy(
+ IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* LFT Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lft_rcv_construct or osm_lft_rcv_init.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_construct,
+* osm_lft_rcv_init
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_init
+* NAME
+* osm_lft_rcv_init
+*
+* DESCRIPTION
+* The osm_lft_rcv_init function initializes a
+* LFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lft_rcv_init(
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other LFT Receiver methods.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_construct,
+* osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_process
+* NAME
+* osm_lft_rcv_process
+*
+* DESCRIPTION
+* Process the LFT attribute.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_process(
+ IN const osm_lft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's LFT attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT processing was successful.
+*
+* NOTES
+* This function processes a LFT attribute.
+*
+* SEE ALSO
+* LFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFT_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lft_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * LFT attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFT_RCV_CTRL_H_
+#define _OSM_LFT_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LFT Receive Controller
+* NAME
+* LFT Receive Controller
+*
+* DESCRIPTION
+* The LFT Receive Controller object
+* encapsulates the information
+* needed to receive the NodeDescription attribute from a node.
+*
+* The LFT Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_t
+* NAME
+* osm_lft_rcv_ctrl_t
+*
+* DESCRIPTION
+* LFT Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv_ctrl
+{
+ osm_lft_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lft_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the LFT Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* LFT Receive Controller object
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_construct
+* NAME
+* osm_lft_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a LFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_construct(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a LFT Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lft_rcv_ctrl_init, osm_lft_rcv_ctrl_destroy
+*
+* Calling osm_lft_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_init,
+* osm_lft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_destroy
+* NAME
+* osm_lft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lft_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_destroy(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* LFT Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lft_rcv_ctrl_construct or osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+* osm_lft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_init
+* NAME
+* osm_lft_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lft_rcv_ctrl_init function initializes a
+* LFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl,
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lft_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other LFT Receive Controller methods.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+* osm_lft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_LFT_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lin_fwd_tbl_t.
+ * This object represents a linear forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LIN_FWD_TBL_H_
+#define _OSM_LIN_FWD_TBL_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table
+* NAME
+* Linear Forwarding Table
+*
+* DESCRIPTION
+* The Linear Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage linear forwarding tables. The OpenSM
+* allocates one Linear Forwarding Table object per switch in the
+* IBA subnet, if that switch uses a linear table.
+*
+* The Linear Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Forwarding Table/osm_lin_fwd_tbl_t
+* NAME
+* osm_lin_fwd_tbl_t
+*
+* DESCRIPTION
+* Linear Forwarding Table structure.
+*
+* Callers may directly access this object.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lin_fwd_tbl
+{
+ uint16_t size;
+ uint8_t port_tbl[1];
+
+} osm_lin_fwd_tbl_t;
+/*
+* FIELDS
+* Size
+* Number of entries in the linear forwarding table. This value
+* is taken from the SwitchInfo attribute.
+*
+* port_tbl
+* The array that specifies the port number which routes the
+* corresponding LID. Index is by LID.
+*
+* SEE ALSO
+* Forwarding Table object, Random Fowarding Table object.
+*********/
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_new
+* NAME
+* osm_lin_tbl_new
+*
+* DESCRIPTION
+* This function creates and initializes a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+ IN uint16_t const size );
+/*
+* PARAMETERS
+* size
+* [in] Number of entries in the Linear Forwarding Table.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_delete
+* NAME
+* osm_lin_tbl_delete
+*
+* DESCRIPTION
+* This destroys and deallocates a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_lin_tbl_delete(
+ IN osm_lin_fwd_tbl_t** const pp_tbl );
+/*
+* PARAMETERS
+* pp_tbl
+* [in] Pointer a Pointer to the Linear Forwarding Table object.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set
+* NAME
+* osm_lin_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lin_fwd_tbl_set(
+ IN osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ CL_ASSERT( lid_ho < p_tbl->size );
+ if( lid_ho < p_tbl->size )
+ p_tbl->port_tbl[lid_ho] = port;
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get
+* NAME
+* osm_lin_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lin_fwd_tbl_get(
+ IN const osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho )
+{
+ if( lid_ho < p_tbl->size )
+ return( p_tbl->port_tbl[lid_ho] );
+ else
+ return( 0xFF );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_size
+* NAME
+* osm_lin_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_size(
+ IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+ return( p_tbl->size );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_lids_per_block
+* NAME
+* osm_lin_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_lids_per_block(
+ IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ return( 64 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_lin_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ return( (uint16_t)(lid_top_ho /
+ osm_lin_fwd_tbl_get_lids_per_block( p_tbl ) ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set_block
+* NAME
+* osm_lin_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Linear Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_lin_fwd_tbl_set_block(
+ IN osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ uint16_t lid_start;
+ uint16_t num_lids;
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( p_block );
+
+ num_lids = osm_lin_fwd_tbl_get_lids_per_block( p_tbl );
+ lid_start = (uint16_t)(block_num * num_lids);
+
+ if( lid_start + num_lids > p_tbl->size )
+ return( IB_INVALID_PARAMETER );
+
+ cl_memcpy( &p_tbl->port_tbl[lid_start], p_block, num_lids );
+ return( IB_SUCCESS );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* p_block
+* [in] Pointer to the Forwarding Table block.
+*
+* block_num
+* [in] Block number of this block.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LIN_FWD_TBL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_link_mgr_t.
+ * This object represents the Link Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LINK_MGR_H_
+#define _OSM_LINK_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Manager
+* NAME
+* Link Manager
+*
+* DESCRIPTION
+* The Link Manager object encapsulates the information
+* needed to control unicast LID forwarding on the subnet.
+*
+* The Link Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Link Manager/osm_link_mgr_t
+* NAME
+* osm_link_mgr_t
+*
+* DESCRIPTION
+* Link Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_link_mgr
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ boolean_t send_set_reqs;
+
+} osm_link_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Link Manager object
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_construct
+* NAME
+* osm_link_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Link Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_construct(
+ IN osm_link_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Link Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_link_mgr_destroy
+*
+* Calling osm_link_mgr_construct is a prerequisite to calling any other
+* method except osm_link_mgr_init.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_init,
+* osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_destroy
+* NAME
+* osm_link_mgr_destroy
+*
+* DESCRIPTION
+* The osm_link_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_destroy(
+ IN osm_link_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Link Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_link_mgr_construct or osm_link_mgr_init.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_construct,
+* osm_link_mgr_init
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_init
+* NAME
+* osm_link_mgr_init
+*
+* DESCRIPTION
+* The osm_link_mgr_init function initializes a
+* Link Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_link_mgr_init(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_link_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Link Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Manager methods.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_construct,
+* osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_process
+* NAME
+* osm_link_mgr_process
+*
+* DESCRIPTION
+* Processes all ports in the subnet per the link manager command.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_link_mgr_process(
+ IN osm_link_mgr_t* const p_mgr,
+ IN const uint8_t link_state );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_link_mgr_t object.
+*
+* link_state
+* [in] state to which to the set the port.
+*
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+* Link Manager, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LINK_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+
+#ifndef _OSM_LOG_H_
+#define _OSM_LOG_H_
+
+#ifndef __WIN__
+#include <syslog.h>
+#endif
+#include <complib/cl_log.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <iba/ib_types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#ifndef PRIx64
+#if __WORDSIZE == 64
+#define __PRI64_PREFIX "l"
+#else
+#define __PRI64_PREFIX "L"
+#endif
+
+#define PRId64 __PRI64_PREFIX"d"
+#define PRIo64 __PRI64_PREFIX"o"
+#define PRIu64 __PRI64_PREFIX"u"
+#define PRIx64 __PRI64_PREFIX"x"
+#endif
+
+#define LOG_ENTRY_SIZE_MAX 4096
+#define BUF_SIZE LOG_ENTRY_SIZE_MAX
+
+#define OSM_LOG_DEFINE_FUNC( NAME ) \
+ static const char osm_log_func_name[] = #NAME
+
+#define OSM_LOG_ENTER( OSM_LOG_PTR, NAME ) \
+ OSM_LOG_DEFINE_FUNC( NAME ); \
+ osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+ "%s: [\n", osm_log_func_name );
+
+#define OSM_LOG_EXIT( OSM_LOG_PTR ) \
+ osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+ "%s: ]\n", osm_log_func_name );
+
+/****h* OpenSM/Log
+* NAME
+* Log
+*
+* DESCRIPTION
+*
+* AUTHOR
+*
+*********/
+typedef uint8_t osm_log_level_t;
+
+#define OSM_LOG_NONE 0x00
+#define OSM_LOG_ERROR 0x01
+#define OSM_LOG_INFO 0x02
+#define OSM_LOG_VERBOSE 0x04
+#define OSM_LOG_DEBUG 0x08
+#define OSM_LOG_FUNCS 0x10
+#define OSM_LOG_FRAMES 0x20
+#define OSM_LOG_ROUTING 0x40
+#define OSM_LOG_SYS 0x80
+
+/*
+ DEFAULT - turn on ERROR and INFO only
+*/
+#define OSM_LOG_DEFAULT_LEVEL OSM_LOG_ERROR | OSM_LOG_INFO
+
+/****s* OpenSM: MAD Wrapper/osm_log_t
+* NAME
+* osm_log_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_log
+{
+ osm_log_level_t level;
+ cl_spinlock_t lock;
+ boolean_t flush;
+ FILE* out_port;
+} osm_log_t;
+/*********/
+
+
+/****f* OpenSM: Log/osm_log_construct
+* NAME
+* osm_log_construct
+*
+* DESCRIPTION
+* This function constructs a Log object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_construct(
+ IN osm_log_t* const p_log )
+{
+ cl_spinlock_construct( &p_log->lock );
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a Log object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_log_init, osm_log_destroy
+*
+* Calling osm_log_construct is a prerequisite to calling any other
+* method except osm_log_init.
+*
+* SEE ALSO
+* Log object, osm_log_init,
+* osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_destroy
+* NAME
+* osm_log_destroy
+*
+* DESCRIPTION
+* The osm_log_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_destroy(
+ IN osm_log_t* const p_log )
+{
+ cl_spinlock_destroy( &p_log->lock );
+ if (p_log->out_port != stdout) {
+ fclose(p_log->out_port);
+ p_log->out_port = stdout;
+ }
+ closelog();
+}
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Log object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_log_construct or osm_log_init.
+*
+* SEE ALSO
+* Log object, osm_log_construct,
+* osm_log_init
+*********/
+
+/****f* OpenSM: Log/osm_log_init
+* NAME
+* osm_log_init
+*
+* DESCRIPTION
+* The osm_log_init function initializes a
+* Log object for use.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_log_init(
+ IN osm_log_t* const p_log,
+ IN const boolean_t flush,
+ IN const uint8_t log_flags,
+ IN const char *log_file)
+{
+ p_log->level = log_flags;
+ p_log->flush = flush;
+
+ if (log_file == NULL)
+ {
+ p_log->out_port = stdout;
+ }
+ else
+ {
+ p_log->out_port = fopen(log_file,"a+");
+ if (!p_log->out_port)
+ {
+ printf("Cannot open %s for appending. Permission denied\n", log_file);
+ return(IB_UNKNOWN_ERROR);
+ }
+ }
+ openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+ if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS)
+ return IB_SUCCESS;
+ else
+ return IB_ERROR;
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object.
+*
+* flush
+* [in] Set to TRUE directs the log to flush all log messages
+* immediately. This severely degrades log performance,
+* and is normally used for debugging only.
+*
+* log_flags
+* [in] The log verbosity level to be used.
+*
+* log_file
+* [in] if not NULL defines the name of the log file. Otherwise it is stdout.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Log object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Log methods.
+*
+* SEE ALSO
+* Log object, osm_log_construct,
+* osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_get_level
+* NAME
+* osm_log_get_level
+*
+* DESCRIPTION
+* Returns the current log level.
+*
+* SYNOPSIS
+*/
+static inline osm_log_level_t
+osm_log_get_level(
+ IN const osm_log_t* const p_log )
+{
+ return( p_log->level );
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* Returns the current log level.
+*
+* NOTES
+*
+* SEE ALSO
+* Log object, osm_log_construct,
+* osm_log_destroy
+*********/
+/****f* OpenSM: Log/osm_log_set_level
+* NAME
+* osm_log_set_level
+*
+* DESCRIPTION
+* Sets the current log level.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_set_level(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t level )
+{
+ p_log->level = level;
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object.
+*
+* level
+* [in] New level to set.
+*
+* RETURN VALUES
+* Returns the current log level.
+*
+* NOTES
+*
+* SEE ALSO
+* Log object, osm_log_construct,
+* osm_log_destroy
+*********/
+/****f* OpenSM: Log/osm_log_is_active
+* NAME
+* osm_log_is_active
+*
+* DESCRIPTION
+* Returns TRUE if the specified log level would be logged.
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_log_is_active(
+ IN const osm_log_t* const p_log,
+ IN const osm_log_level_t level )
+{
+ return( (p_log->level & level) != 0 );
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object.
+*
+* level
+* [in] Level to check.
+*
+* RETURN VALUES
+* Returns TRUE if the specified log level would be logged.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Log object, osm_log_construct,
+* osm_log_destroy
+*********/
+
+
+void
+osm_log(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_str, ... );
+
+void
+osm_log_raw(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_buf );
+
+#define DBG_CL_LOCK 0
+
+#define CL_PLOCK_EXCL_ACQUIRE( __exp__ ) \
+{ \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_excl_acquire: Acquiring %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+ cl_plock_excl_acquire( __exp__ ); \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_excl_acquire: Acquired %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+}
+
+#define CL_PLOCK_ACQUIRE( __exp__ ) \
+{ \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_acquire: Acquiring %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+ cl_plock_acquire( __exp__ ); \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_acquire: Acquired %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+}
+
+#define CL_PLOCK_RELEASE( __exp__ ) \
+{ \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_release: Releasing %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+ cl_plock_release( __exp__ ); \
+ if (DBG_CL_LOCK) \
+ printf("cl_plock_release: Released %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+}
+
+#define DBG_CL_SPINLOCK 0
+#define CL_SPINLOCK_RELEASE( __exp__ ) \
+{ \
+ if (DBG_CL_SPINLOCK) \
+ printf("cl_spinlock_release: Releasing %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+ cl_spinlock_release( __exp__ ); \
+ if (DBG_CL_SPINLOCK) \
+ printf("cl_spinlock_release: Released %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+}
+
+#define CL_SPINLOCK_ACQUIRE( __exp__ ) \
+{ \
+ if (DBG_CL_SPINLOCK) \
+ printf("cl_spinlock_acquire: Acquire %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+ cl_spinlock_acquire( __exp__ ); \
+ if (DBG_CL_SPINLOCK) \
+ printf("cl_spinlock_acquire: Acquired %p file %s, line %d\n", \
+ __exp__,__FILE__, __LINE__); \
+}
+
+/****f* OpenSM: Helper/osm_is_debug
+* NAME
+* osm_is_debug
+*
+* DESCRIPTION
+* The osm_is_debug function returns TRUE if the opensm was compiled
+* in debug mode, and FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_is_debug(void);
+/*
+* PARAMETERS
+* None
+*
+* RETURN VALUE
+* TRUE if compiled in debug version. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LOG_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mad_pool_t.
+ * This object represents a pool of management datagram (MAD) objects.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MAD_POOL_H_
+#define _OSM_MAD_POOL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MAD Pool
+* NAME
+* MAD Pool
+*
+* DESCRIPTION
+* The MAD Pool encapsulates the information needed by the
+* OpenSM to manage a pool of MAD objects. The OpenSM allocates
+* one MAD Pool per IBA subnet.
+*
+* The MAD Pool is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MAD Pool/osm_mad_pool_t
+* NAME
+* osm_mad_pool_t
+*
+* DESCRIPTION
+* MAD Pool structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mad_pool
+{
+ osm_log_t *p_log;
+ cl_qlock_pool_t madw_pool;
+ atomic32_t mads_out;
+} osm_mad_pool_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* lock
+* Spinlock guarding the pool.
+*
+* mads_out
+* Running total of the number of MADs outstanding.
+*
+* SEE ALSO
+* MAD Pool
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_construct
+* NAME
+* osm_mad_pool_construct
+*
+* DESCRIPTION
+* This function constructs a MAD Pool.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_construct(
+ IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to a MAD Pool to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mad_pool_init, osm_mad_pool_destroy
+*
+* Calling osm_mad_pool_construct is a prerequisite to calling any other
+* method except osm_mad_pool_init.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_init, osm_mad_pool_destroy
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_destroy
+* NAME
+* osm_mad_pool_destroy
+*
+* DESCRIPTION
+* The osm_mad_pool_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_destroy(
+ IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to a MAD Pool to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified MAD Pool.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mad_pool_construct or
+* osm_mad_pool_init.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_construct, osm_mad_pool_init
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_init
+* NAME
+* osm_mad_pool_init
+*
+* DESCRIPTION
+* The osm_mad_pool_init function initializes a MAD Pool for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mad_pool_init(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object to initialize.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+*
+* RETURN VALUES
+* CL_SUCCESS if the MAD Pool was initialized successfully.
+*
+* NOTES
+* Allows calling other MAD Pool methods.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_construct, osm_mad_pool_destroy
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get
+* NAME
+* osm_mad_pool_get
+*
+* DESCRIPTION
+* Gets a MAD wrapper and wire MAD from the pool.
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const osm_mad_addr_t* const p_mad_addr );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object.
+*
+* h_bind
+* [in] Handle returned from osm_vendor_bind() call to the
+* port over which this mad will be sent.
+*
+* total_size
+* [in] Total size, including MAD header of the requested MAD.
+*
+* p_mad_addr
+* [in] Pointer to the MAD address structure. This parameter
+* may be NULL for directed route MADs.
+*
+* RETURN VALUES
+* Returns a pointer to a MAD wrapper containing the MAD.
+* A return value of NULL means no MADs are available.
+*
+* NOTES
+* The MAD must eventually be returned to the pool with a call to
+* osm_mad_pool_put.
+*
+* The osm_mad_pool_construct or osm_mad_pool_init must be called before
+* using this function.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_put
+* NAME
+* osm_mad_pool_put
+*
+* DESCRIPTION
+* Returns a MAD to the pool.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_put(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object.
+*
+* p_madw
+* [in] Pointer to a MAD Wrapper for a MAD that was previously
+* retrieved from the pool.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+* The osm_mad_pool_construct or osm_mad_pool_init must be called before
+* using this function.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_get
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper
+* NAME
+* osm_mad_pool_get_wrapper
+*
+* DESCRIPTION
+* Gets a only MAD wrapper from the pool (no wire MAD).
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get_wrapper(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const ib_mad_t* const p_mad,
+ IN const osm_mad_addr_t* const p_mad_addr );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object.
+*
+* h_bind
+* [in] Handle returned from osm_vendor_bind() call to the
+* port for which this mad wrapper will be used.
+*
+* total_size
+* [in] Total size, including MAD header of the MAD that will
+* be attached to this wrapper.
+*
+* p_mad
+* [in] Pointer to the MAD to attach to this wrapper.
+*
+* p_mad_addr
+* [in] Pointer to the MAD address structure. This parameter
+* may be NULL for directed route MADs.
+*
+* RETURN VALUES
+* Returns a pointer to a MAD wrapper.
+* A return value of NULL means no MAD wrappers are available.
+*
+* NOTES
+* The MAD must eventually be returned to the pool with a call to
+* osm_mad_pool_put.
+*
+* The osm_mad_pool_construct or osm_mad_pool_init must be called before
+* using this function.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper_raw
+* NAME
+* osm_mad_pool_get_wrapper_raw
+*
+* DESCRIPTION
+* Gets a only an uninitialized MAD wrapper from the pool (no wire MAD).
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get_wrapper_raw(
+ IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object.
+*
+* RETURN VALUES
+* Returns a pointer to a MAD wrapper.
+* A return value of NULL means no MAD wrappers are available.
+*
+* NOTES
+* The MAD must eventually be returned to the pool with a call to
+* osm_mad_pool_put.
+*
+* The osm_mad_pool_construct or osm_mad_pool_init must be called before
+* using this function.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_outstanding
+* NAME
+* osm_mad_pool_get_count
+*
+* DESCRIPTION
+* Returns the running count of MADs currently outstanding from the pool.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_mad_pool_get_outstanding(
+ IN const osm_mad_pool_t* const p_pool )
+{
+ return( p_pool->mads_out );
+}
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object.
+*
+* RETURN VALUES
+* Returns the running count of MADs currently outstanding from the pool.
+*
+* NOTES
+* The osm_mad_pool_construct or osm_mad_pool_init must be called before
+* using this function.
+*
+* SEE ALSO
+* MAD Pool, osm_mad_pool_get
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MAD_POOL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mad_wrapper_t.
+ * This object represents the context wrapper for OpenSM MAD processing.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_MADW_H_
+#define _OSM_MADW_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: MAD Wrapper/osm_bind_info_t
+* NAME
+* osm_bind_info_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_bind_info
+{
+ ib_net64_t port_guid;
+ uint8_t mad_class;
+ uint8_t class_version;
+ boolean_t is_responder;
+ boolean_t is_trap_processor;
+ boolean_t is_report_processor;
+ uint32_t send_q_size;
+ uint32_t recv_q_size;
+
+} osm_bind_info_t;
+/*
+* FIELDS
+* portguid
+* PortGuid of local port
+*
+* class
+* Mgmt Class ID
+*
+* class_version
+* Mgmt Class version
+*
+* is_responder
+* True if this is a GSI Agent
+*
+* is_trap_processor
+* True if GSI Trap msgs are handled
+*
+* is_report_processo
+* True if GSI Report msgs are handled
+*
+* send_q_size
+* SendQueueSize
+*
+* recv_q_size
+* Receive Queue Size
+*
+* SEE ALSO
+*********/
+
+/****h* OpenSM/MAD Wrapper
+* NAME
+* MAD Wrapper
+*
+* DESCRIPTION
+* The MAD Wrapper object encapsulates the information needed by the
+* OpenSM to manage individual MADs. The OpenSM allocates one MAD Wrapper
+* per MAD.
+*
+* The MAD Wrapper is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: MAD Wrapper/osm_ni_context_t
+* NAME
+* osm_ni_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_context
+{
+ ib_net64_t node_guid;
+ uint8_t port_num;
+
+} osm_ni_context_t;
+/*
+* FIELDS
+* p_node
+* Pointer to the node thru which we got to this node.
+*
+* p_sw
+* Pointer to the switch object (if any) of the switch
+* thru which we got to this node.
+*
+* port_num
+* Port number on the node or switch thru which we got
+* to this node.
+*
+* SEE ALSO
+*********/
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_pi_context_t
+* NAME
+* osm_pi_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_context
+{
+ ib_net64_t node_guid;
+ ib_net64_t port_guid;
+ boolean_t set_method;
+ boolean_t light_sweep;
+ boolean_t update_master_sm_base_lid;
+ boolean_t ignore_errors;
+} osm_pi_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_nd_context_t
+* NAME
+* osm_nd_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of NodeDescription attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_context
+{
+ ib_net64_t node_guid;
+
+} osm_nd_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_si_context_t
+* NAME
+* osm_si_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_context
+{
+ ib_net64_t node_guid;
+ boolean_t set_method;
+ boolean_t light_sweep;
+
+} osm_si_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_lft_context_t
+* NAME
+* osm_lft_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of LinearForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_context
+{
+ ib_net64_t node_guid;
+ boolean_t set_method;
+
+} osm_lft_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_mft_context_t
+* NAME
+* osm_mft_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of MulticastForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_context
+{
+ ib_net64_t node_guid;
+ boolean_t set_method;
+
+} osm_mft_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_smi_context_t
+* NAME
+* osm_smi_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of SMInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smi_context
+{
+ ib_net64_t port_guid;
+ boolean_t set_method;
+
+} osm_smi_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_pkey_context_t
+* NAME
+* osm_pkey_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of P_Key attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_context
+{
+ ib_net64_t node_guid;
+ ib_net64_t port_guid;
+ boolean_t set_method;
+} osm_pkey_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_slvl_context_t
+* NAME
+* osm_slvl_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_context
+{
+ ib_net64_t node_guid;
+ ib_net64_t port_guid;
+ boolean_t set_method;
+} osm_slvl_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_vla_context_t
+* NAME
+* osm_vla_context_t
+*
+* DESCRIPTION
+* Context needed by recipient of VL Arb attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_context
+{
+ ib_net64_t node_guid;
+ ib_net64_t port_guid;
+ boolean_t set_method;
+} osm_vla_context_t;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_arbitrary_context_t
+* NAME
+* osm_sa_context_t
+*
+* DESCRIPTION
+* Context needed by arbitrary recipient.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_arbitrary_context
+{
+ void* context1;
+ void* context2;
+} osm_arbitrary_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_madw_context_t
+* NAME
+* osm_madw_context_t
+*
+* DESCRIPTION
+* Context needed by recipients of MAD responses.
+*
+* SYNOPSIS
+*/
+typedef union _osm_madw_context
+{
+ osm_ni_context_t ni_context;
+ osm_pi_context_t pi_context;
+ osm_nd_context_t nd_context;
+ osm_si_context_t si_context;
+ osm_lft_context_t lft_context;
+ osm_mft_context_t mft_context;
+ osm_smi_context_t smi_context;
+ osm_slvl_context_t slvl_context;
+ osm_pkey_context_t pkey_context;
+ osm_arbitrary_context_t arb_context;
+} osm_madw_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_mad_addr_t
+* NAME
+* osm_mad_addr_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mad_addr
+{
+ ib_net16_t dest_lid;
+ uint8_t path_bits;
+ uint8_t static_rate;
+
+ union addr_type
+ {
+ struct _smi
+ {
+ ib_net16_t source_lid;
+ uint8_t port_num;
+ } smi;
+
+ struct _gsi
+ {
+ ib_net32_t remote_qp;
+ ib_net32_t remote_qkey;
+ ib_net16_t pkey;
+ uint8_t service_level;
+ boolean_t global_route;
+ ib_grh_t grh_info;
+ } gsi;
+ } addr_type;
+
+} osm_mad_addr_t;
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+
+
+/****s* OpenSM: MAD Wrapper/osm_madw_t
+* NAME
+* osm_madw_t
+*
+* DESCRIPTION
+* Context needed for processing individual MADs
+*
+* SYNOPSIS
+*/
+typedef struct _osm_madw
+{
+ cl_pool_item_t pool_item;
+ osm_bind_handle_t h_bind;
+ osm_vend_wrap_t vend_wrap;
+ osm_mad_addr_t mad_addr;
+ osm_bind_info_t bind_info;
+ osm_madw_context_t context;
+ uint32_t mad_size;
+ ib_api_status_t status;
+ cl_disp_msgid_t fail_msg;
+ boolean_t resp_expected;
+ const ib_mad_t *p_mad;
+
+} osm_madw_t;
+/*
+* FIELDS
+* pool_item
+* List linkage for pools and lists. MUST BE FIRST MEMBER!
+*
+* h_bind
+* Bind handle for the port on which this MAD will be sent
+* or was received.
+*
+* vend_wrap
+* Transport vendor specific context. This structure is not
+* used outside MAD transport vendor specific code.
+*
+* context
+* Union of controller specific contexts needed for this MAD.
+* This structure allows controllers to indirectly communicate
+* with each other through the dispatcher.
+*
+* mad_size
+* Size of this MAD in bytes.
+*
+* status
+* Status of completed operation on the MAD.
+* CL_SUCCESS if the operation was successful.
+*
+* fail_msg
+* Dispatcher message with which to post this MAD on failure.
+* This value is set by the originator of the MAD.
+* If an operation on this MAD fails, for example due to a timeout,
+* then the transport layer will dispose of the MAD by sending
+* it through the Dispatcher with this message type. Presumably,
+* there is a controller listening for the failure message that can
+* properly clean up.
+*
+* resp_expected
+* TRUE if a response is expected to this MAD.
+* FALSE otherwise.
+*
+* p_mad
+* Pointer to the wire MAD. The MAD itself cannot be part of the
+* wrapper, since wire MADs typically reside in special memory
+* registered with the local HCA.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_construct
+* NAME
+* osm_madw_construct
+*
+* DESCRIPTION
+* This function constructs a MAD Wrapper object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_construct(
+ IN osm_madw_t* const p_madw )
+{
+ /*
+ Don't touch the pool_item since that is an opaque object.
+ Clear all other objects in the mad wrapper.
+ */
+ cl_memclr( ((uint8_t *)p_madw) + sizeof( cl_pool_item_t ),
+ sizeof(*p_madw) - sizeof( cl_pool_item_t ) );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to a MAD Wrapper object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_madw_init, osm_madw_destroy
+*
+* Calling osm_madw_construct is a prerequisite to calling any other
+* method except osm_madw_init.
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_init, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_destroy
+* NAME
+* osm_madw_destroy
+*
+* DESCRIPTION
+* The osm_madw_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_madw_destroy(
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to a MAD Wrapper object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified MAD Wrapper object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_madw_construct or
+* osm_madw_init.
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_construct, osm_madw_init
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_init
+* NAME
+* osm_madw_init
+*
+* DESCRIPTION
+* Initializes a MAD Wrapper object for use.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_init(
+ IN osm_madw_t* const p_madw,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t mad_size,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_construct( p_madw );
+ p_madw->h_bind = h_bind;
+ p_madw->fail_msg = CL_DISP_MSGID_NONE;
+ p_madw->mad_size = mad_size;
+ if( p_mad_addr )
+ p_madw->mad_addr = *p_mad_addr;
+ p_madw->resp_expected = FALSE;
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object to initialize.
+*
+* h_bind
+* [in] Pointer to the wire MAD.
+*
+* p_mad_addr
+* [in] Pointer to the MAD address structure. This parameter may
+* be NULL for directed route MADs.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_smp_ptr
+* NAME
+* osm_madw_get_smp_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SMP in this MAD.
+*
+* SYNOPSIS
+*/
+static inline ib_smp_t*
+osm_madw_get_smp_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (ib_smp_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object to initialize.
+*
+* RETURN VALUES
+* Pointer to the start of the SMP MAD.
+*
+* NOTES
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_sa_mad_ptr
+* NAME
+* osm_madw_get_sa_mad_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SA MAD in this MAD wrapper.
+*
+* SYNOPSIS
+*/
+static inline ib_sa_mad_t*
+osm_madw_get_sa_mad_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (ib_sa_mad_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object to initialize.
+*
+* RETURN VALUES
+* Pointer to the start of the SMP MAD.
+*
+* NOTES
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_ni_context_ptr
+* NAME
+* osm_madw_get_ni_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the NodeInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_ni_context_t*
+osm_madw_get_ni_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_ni_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_pi_context_ptr
+* NAME
+* osm_madw_get_pi_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the PortInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_pi_context_t*
+osm_madw_get_pi_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_pi_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_nd_context_ptr
+* NAME
+* osm_madw_get_nd_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the NodeDescription context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_nd_context_t*
+osm_madw_get_nd_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_nd_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_lft_context_ptr
+* NAME
+* osm_madw_get_lft_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the LFT context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_lft_context_t*
+osm_madw_get_lft_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_lft_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mft_context_ptr
+* NAME
+* osm_madw_get_mft_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the MFT context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_mft_context_t*
+osm_madw_get_mft_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_mft_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_si_context_ptr
+* NAME
+* osm_madw_get_si_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SwitchInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_si_context_t*
+osm_madw_get_si_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_si_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_smi_context_ptr
+* NAME
+* osm_madw_get_smi_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the SMInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_smi_context_t*
+osm_madw_get_smi_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_smi_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_pkey_context_ptr
+* NAME
+* osm_madw_get_pkey_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the P_Key context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_pkey_context_t*
+osm_madw_get_pkey_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_pkey_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_slvl_context_ptr
+* NAME
+* osm_madw_get_slvl_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the PortInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_slvl_context_t*
+osm_madw_get_slvl_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_slvl_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vla_context_ptr
+* NAME
+* osm_madw_get_vla_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the Vl Arb context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_vla_context_t*
+osm_madw_get_vla_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_vla_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: MAD Wrapper/osm_madw_get_arbitrary_context_ptr
+* NAME
+* osm_madw_get_arbitrary_context_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the arbitrary context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_arbitrary_context_t*
+osm_madw_get_arbitrary_context_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_arbitrary_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr
+* NAME
+* osm_madw_get_vend_ptr
+*
+* DESCRIPTION
+* Gets a pointer to the vendor specific MAD wrapper component.
+*
+* SYNOPSIS
+*/
+static inline osm_vend_wrap_t*
+osm_madw_get_vend_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_vend_wrap_t*)&p_madw->vend_wrap );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Gets a pointer to the vendor specific MAD wrapper component.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr
+* NAME
+* osm_madw_get_vend_ptr
+*
+* DESCRIPTION
+* Returns the bind handle associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_madw_get_bind_handle(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_bind_handle_t)p_madw->h_bind );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Returns the bind handle associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_addr_ptr
+* NAME
+* osm_madw_get_mad_addr_ptr
+*
+* DESCRIPTION
+* Returns the mad address structure associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_mad_addr_t*
+osm_madw_get_mad_addr_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (osm_mad_addr_t*)&p_madw->mad_addr );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Returns the mad address structure associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_ptr
+* NAME
+* osm_madw_get_mad_ptr
+*
+* DESCRIPTION
+* Returns the mad address structure associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline ib_mad_t*
+osm_madw_get_mad_ptr(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (ib_mad_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Returns the mad address structure associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_err_msg
+* NAME
+* osm_madw_get_err_msg
+*
+* DESCRIPTION
+* Returns the message with which to post this mad wrapper if
+* an error occurs during processing the mad.
+*
+* SYNOPSIS
+*/
+static inline cl_disp_msgid_t
+osm_madw_get_err_msg(
+ IN const osm_madw_t* const p_madw )
+{
+ return( (cl_disp_msgid_t)p_madw->fail_msg );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+* Returns the message with which to post this mad wrapper if
+* an error occurs during processing the mad.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_set_mad
+* NAME
+* osm_madw_set_mad
+*
+* DESCRIPTION
+* Associates a wire MAD with this MAD Wrapper object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_set_mad(
+ IN osm_madw_t* const p_madw,
+ IN const ib_mad_t* const p_mad )
+{
+ p_madw->p_mad = p_mad;
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to an osm_madw_t object.
+*
+* p_mad
+* [in] Pointer to the wire MAD to attach to this wrapper.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_copy_context
+* NAME
+* osm_madw_copy_context
+*
+* DESCRIPTION
+* Copies the controller context from one MAD Wrapper to another.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_copy_context(
+ IN osm_madw_t* const p_dest,
+ IN const osm_madw_t* const p_src )
+{
+ p_dest->context = p_src->context;
+}
+/*
+* PARAMETERS
+* p_dest
+* [in] Pointer to the destination osm_madw_t object.
+*
+* p_src
+* [in] Pointer to the source osm_madw_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MADW_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lid_matrix_t.
+ * This object represents a two dimensional array of port numbers
+ * and LID values.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_MATRIX_H_
+#define _OSM_MATRIX_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_vector.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LID Matrix
+* NAME
+* LID Matrix
+*
+* DESCRIPTION
+* The LID Matrix object encapsulates the information needed by the
+* OpenSM to manage fabric routes. It is a two dimensional array
+* index by LID value and Port Number. Each element contains the
+* number of hops from that Port Number to the LID.
+* Every Switch object contains a LID Matrix.
+*
+* The LID Matrix is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: LID Matrix/osm_lid_matrix_t
+* NAME
+* osm_lid_matrix_t
+*
+* DESCRIPTION
+*
+* The LID Matrix object encapsulates the information needed by the
+* OpenSM to manage fabric routes. It is a two dimensional array
+* index by LID value and Port Number. Each element contains the
+* number of hops from that Port Number to the LID.
+* Every Switch object contains a LID Matrix.
+*
+* The LID Matrix is not thread safe, thus callers must provide
+* serialization.
+*
+* The num_ports index into the matrix serves a special purpose, in that it
+* contains the shortest hop path for that LID through any port.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lid_matrix_t
+{
+ cl_vector_t lid_vec;
+ uint8_t num_ports;
+
+} osm_lid_matrix_t;
+/*
+* FIELDS
+* lid_vec
+* Vector (indexed by LID) of port arrays (indexed by port number)
+*
+* num_ports
+* Number of ports at each entry in the LID vector.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_construct
+* NAME
+* osm_lid_matrix_construct
+*
+* DESCRIPTION
+* This function constructs a LID Matrix object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lid_matrix_construct(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ p_lmx->num_ports = 0;
+ cl_vector_construct( &p_lmx->lid_vec );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to a LID Matrix object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lid_matrix_init, osm_lid_matrix_destroy
+*
+* Calling osm_lid_matrix_construct is a prerequisite to calling any other
+* method except osm_lid_matrix_init.
+*
+* SEE ALSO
+* LID Matrix object, osm_lid_matrix_init, osm_lid_matrix_destroy
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_destroy
+* NAME
+* osm_lid_matrix_destroy
+*
+* DESCRIPTION
+* The osm_lid_matrix_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lid_matrix_destroy(
+ IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to a LID Matrix object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified LID Matrix object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_lid_matrix_construct or
+* osm_lid_matrix_init.
+*
+* SEE ALSO
+* LID Matrix object, osm_lid_matrix_construct, osm_lid_matrix_init
+*********/
+/****f* OpenSM: LID Matrix/osm_lid_matrix_init
+* NAME
+* osm_lid_matrix_init
+*
+* DESCRIPTION
+* Initializes a LID Matrix object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lid_matrix_init(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint8_t num_ports );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object to initialize.
+*
+* num_ports
+* [in] Number of ports at each LID index. This value is fixed
+* at initialization time.
+*
+* RETURN VALUES
+* IB_SUCCESS on success
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get
+* NAME
+* osm_lid_matrix_get
+*
+* DESCRIPTION
+* Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get(
+ IN const osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num )
+{
+ CL_ASSERT( port_num < p_lmx->num_ports );
+ CL_ASSERT( lid_ho <cl_vector_get_size(&p_lmx->lid_vec) );
+ return( ((uint8_t *)cl_vector_get_ptr(
+ &p_lmx->lid_vec, lid_ho ))[port_num] );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] LID value (host order) for which to return the hop count
+*
+* port_num
+* [in] Port number in the switch
+*
+* RETURN VALUES
+* Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_max_lid_ho
+* NAME
+* osm_lid_matrix_get_max_lid_ho
+*
+* DESCRIPTION
+* Returns the maximum LID (host order) value contained
+* in the matrix.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lid_matrix_get_max_lid_ho(
+ IN const osm_lid_matrix_t* const p_lmx )
+{
+ return( (uint16_t)(cl_vector_get_size( &p_lmx->lid_vec ) - 1 ) );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+* Returns the maximum LID (host order) value contained
+* in the matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_num_ports
+* NAME
+* osm_lid_matrix_get_num_ports
+*
+* DESCRIPTION
+* Returns the number of ports in this lid matrix.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_num_ports(
+ IN const osm_lid_matrix_t* const p_lmx )
+{
+ return( p_lmx->num_ports );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+* Returns the number of ports in this lid matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_least_hops
+* NAME
+* osm_lid_matrix_get_least_hops
+*
+* DESCRIPTION
+* Returns the number of ports in this lid matrix.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_least_hops(
+ IN const osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho )
+{
+ if( lid_ho > osm_lid_matrix_get_max_lid_ho( p_lmx ) )
+ return( OSM_NO_PATH );
+
+ return( ((uint8_t *)cl_vector_get_ptr(
+ &p_lmx->lid_vec, lid_ho ))[p_lmx->num_ports] );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+* Returns the number of ports in this lid matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set
+* NAME
+* osm_lid_matrix_set
+*
+* DESCRIPTION
+* Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+cl_status_t
+osm_lid_matrix_set(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t val );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] LID value (host order) to index into the vector.
+*
+* port_num
+* [in] port number index into the vector entry.
+*
+* val
+* [in] value (number of hops) to assign to this entry.
+*
+* RETURN VALUES
+* Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set_min_lid_size
+* NAME
+* osm_lid_matrix_set_min_lid_size
+*
+* DESCRIPTION
+* Sets the size of the matrix to at least accomodate the
+* specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_lid_matrix_set_min_lid_size(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho )
+{
+ return( cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 ) );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] Minimum LID value (host order) to accomodate.
+*
+* RETURN VALUES
+* Sets the size of the matrix to at least accomodate the
+* specified LID value (host ordered)
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_clear
+* NAME
+* osm_lid_matrix_clear
+*
+* DESCRIPTION
+* Clears a LID Matrix object in anticipation of a rebuild.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_matrix_clear(
+ IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object to clear.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MATRIX_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcast_conf_ctrl_t.
+ * This object represents a controller that performs a
+ * Set(MulticastForwardingTable) for the specified port.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCAST_CONFIG_CTRL_H_
+#define _OSM_MCAST_CONFIG_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Forwarding Table Configuration Controller
+* NAME
+* Multicast Forwarding Table Configuration Controller
+*
+* DESCRIPTION
+* The Multicast Forwarding Table Configuration Controller object
+* encapsulates the information needed to Set(MulticastForwardingTable)
+* at the specified port.
+*
+* The Multicast Forwarding Table Configuration Controller object
+* is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_t
+* NAME
+* osm_mcast_conf_ctrl_t
+*
+* DESCRIPTION
+* Multicast Forwarding Table Configuration Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_conf_ctrl
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_mcast_conf_ctrl_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller object
+*********/
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_construct
+* NAME
+* osm_mcast_conf_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Forwarding Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mcast_conf_ctrl_construct(
+ IN osm_mcast_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Multicast Forwarding Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcast_conf_ctrl_init, osm_mcast_conf_ctrl_destroy,
+* and osm_mcast_conf_ctrl_is_inited.
+*
+* Calling osm_mcast_conf_ctrl_construct is a prerequisite to calling any other
+* method except osm_mcast_conf_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_init,
+* osm_mcast_conf_ctrl_destroy, osm_mcast_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_destroy
+* NAME
+* osm_mcast_conf_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mcast_conf_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcast_conf_ctrl_destroy(
+ IN osm_mcast_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Multicast Forwarding Table Configuration Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcast_conf_ctrl_construct or osm_mcast_conf_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+* osm_mcast_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_init
+* NAME
+* osm_mcast_conf_ctrl_init
+*
+* DESCRIPTION
+* The osm_mcast_conf_ctrl_init function initializes a
+* Multicast Forwarding Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcast_conf_ctrl_init(
+ IN osm_mcast_conf_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcast_conf_ctrl_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Multicast Forwarding Table Configuration Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Multicast Forwarding Table Configuration Controller methods.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+* osm_mcast_conf_ctrl_destroy, osm_mcast_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_is_inited
+* NAME
+* osm_mcast_conf_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_mcast_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcast_conf_ctrl_is_inited(
+ IN const osm_mcast_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcast_conf_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_mcast_conf_ctrl_construct or osm_mcast_conf_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+* osm_mcast_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_process
+* NAME
+* osm_mcast_conf_ctrl_process
+*
+* DESCRIPTION
+* Initiate a MulticastForwardingTable configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcast_conf_ctrl_process(
+ IN const osm_mcast_conf_ctrl_t* const p_ctrl,
+ IN const ib_guid_t guid );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcast_conf_ctrl_t object.
+*
+* guid
+* [in] Node GUID of switch to configure.
+*
+* RETURN VALUES
+* CL_SUCCESS if configuration processing was successfully
+* initiated.
+*
+* NOTES
+* A success status here does not indicate that
+* the Multicast Forwarding Table configuration completed successfully.
+*
+* SEE ALSO
+* Multicast Forwarding Table Configuration Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCAST_CONFIG_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mft_rcv_t.
+ * This object represents the Multicast Forwarding Table Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MFT_RCV_H_
+#define _OSM_MFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MFT Receiver
+* NAME
+* MFT Receiver
+*
+* DESCRIPTION
+* The MFT Receiver object encapsulates the information
+* needed to receive the MFT attribute from a node.
+*
+* The MFT Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: MFT Receiver/osm_mft_rcv_t
+* NAME
+* osm_mft_rcv_t
+*
+* DESCRIPTION
+* MFT Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_mft_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* MFT Receiver object
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_construct
+* NAME
+* osm_mft_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a MFT Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_construct(
+ IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a MFT Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mft_rcv_init, osm_mft_rcv_destroy
+*
+* Calling osm_mft_rcv_construct is a prerequisite to calling any other
+* method except osm_mft_rcv_init.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_init,
+* osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_destroy
+* NAME
+* osm_mft_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mft_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_destroy(
+ IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* MFT Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mft_rcv_construct or osm_mft_rcv_init.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_construct,
+* osm_mft_rcv_init
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_init
+* NAME
+* osm_mft_rcv_init
+*
+* DESCRIPTION
+* The osm_mft_rcv_init function initializes a
+* MFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_init(
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MFT Receiver methods.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_construct,
+* osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_process
+* NAME
+* osm_mft_rcv_process
+*
+* DESCRIPTION
+* Process the MFT attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_process(
+ IN const osm_mft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's MFT attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT processing was successful.
+*
+* NOTES
+* This function processes a MFT attribute.
+*
+* SEE ALSO
+* MFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFT_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mft_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * Multicast Forwarding Table attribute from a node (specifically, a
+ * switch).
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MFT_RCV_CTRL_H_
+#define _OSM_MFT_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MFT Receive Controller
+* NAME
+* MFT Receive Controller
+*
+* DESCRIPTION
+* The MFT Receive Controller object
+* encapsulates the information
+* needed to receive the Multicast Forwarding Table
+* attribute from a node.
+*
+* The MFT Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_t
+* NAME
+* osm_mft_rcv_ctrl_t
+*
+* DESCRIPTION
+* MFT Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv_ctrl
+{
+ osm_mft_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_mft_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the MFT Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* MFT Receive Controller object
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_construct
+* NAME
+* osm_mft_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a MFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_construct(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a MFT Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mft_rcv_ctrl_init, osm_mft_rcv_ctrl_destroy
+*
+* Calling osm_mft_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_init,
+* osm_mft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_destroy
+* NAME
+* osm_mft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mft_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_destroy(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* MFT Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mft_rcv_ctrl_construct or osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+* osm_mft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_init
+* NAME
+* osm_mft_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mft_rcv_ctrl_init function initializes a
+* MFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl,
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mft_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MFT Receive Controller methods.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+* osm_mft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_MFT_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcast_mgr_t.
+ * This object represents the Multicast Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MCAST_MGR_H_
+#define _OSM_MCAST_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_multicast.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_MCAST_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/Multicast Manager
+* NAME
+* Multicast Manager
+*
+* DESCRIPTION
+* The Multicast Manager object encapsulates the information
+* needed to control multicast LID forwarding on the subnet.
+*
+* The Multicast Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Multicast Manager/osm_mcast_mgr_t
+* NAME
+* osm_mcast_mgr_t
+*
+* DESCRIPTION
+* Multicast Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_mgr
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_mcast_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Multicast Manager object
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_construct
+* NAME
+* osm_mcast_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_construct(
+ IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Multicast Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_mcast_mgr_destroy
+*
+* Calling osm_mcast_mgr_construct is a prerequisite to calling any other
+* method except osm_mcast_mgr_init.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_init,
+* osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_destroy
+* NAME
+* osm_mcast_mgr_destroy
+*
+* DESCRIPTION
+* The osm_mcast_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_destroy(
+ IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Multicast Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcast_mgr_construct or osm_mcast_mgr_init.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_construct,
+* osm_mcast_mgr_init
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_init
+* NAME
+* osm_mcast_mgr_init
+*
+* DESCRIPTION
+* The osm_mcast_mgr_init function initializes a
+* Multicast Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_init(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Multicast Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Multicast Manager methods.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_construct,
+* osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+* osm_mcast_mgr_process
+*
+* DESCRIPTION
+* Process and configure the subnet's multicast forwarding tables.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process(
+ IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+* This function processes the subnet, configuring switch
+* multicast forwarding tables.
+*
+* SEE ALSO
+* Multicast Manager, Node Info Response Controller
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process_mgrp
+* NAME
+* osm_mcast_mgr_process_mgrp
+*
+* DESCRIPTION
+* Processes a specific multicast group. This function is called
+* by the SM to process a multicast group. Note that this function
+* returns BEFORE the switch tables have been configured over the wire,
+* and AFTER switch table configuration MADs are all placed in the
+* VL15 FIFOs. In other words, the switch table configuration is
+* imminent but probably not yet complete at the time this call returns.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process_mgrp(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp,
+ IN osm_mcast_req_type_t req_type,
+ IN ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* p_mgrp
+* [in] Pointer to the multicast group to process.
+*
+* req_type
+* [in] Type of the multicast request that caused this processing
+* (MC create/join/leave).
+*
+* port_guid
+* [in] Port guid of the port that was added/removed due to this call.
+*
+* RETURN VALUES
+* OSM_SIGNAL_DONE
+* OSM_SIGNAL_DONE_PENDING
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process_mgrp_cb
+* NAME
+* osm_mcast_mgr_process_mgrp_cb
+*
+* DESCRIPTION
+* Callback entry point for the osm_mcast_mgr_process_mgrp function.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+ IN void* const Context1,
+ IN void* const Context2 );
+/*
+* PARAMETERS
+* (Context1) p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* (Context2) p_mgrp
+* [in] Pointer to the multicast group to process.
+*
+* RETURN VALUES
+* IB_SUCCESS
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+* osm_mcast_mgr_process_single
+*
+* DESCRIPTION
+* Attempts to add a single port to an existing multicast spanning tree.
+* This function can only succeed if the port to be added is connected
+* to a switch that is already routing traffic for this multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_process_single(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t join_state );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* mlid
+* [in] Multicast LID of relevent multicast group.
+*
+* port_guid
+* [in] GUID of port to attempt to add to the group.
+*
+* join_state
+* [in] Specifies the join state for this port per the spec.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_NOT_DONE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCAST_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcast_tbl_t.
+ * This object represents a multicast forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MCAST_TBL_H_
+#define _OSM_MCAST_TBL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Forwarding Table/osm_mcast_tbl_t
+* NAME
+* osm_mcast_tbl_t
+*
+* DESCRIPTION
+* Multicast Forwarding Table structure.
+*
+* Callers may directly access this object.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_fwd_tbl
+{
+ uint8_t num_ports;
+ uint8_t max_position;
+ uint16_t max_block;
+ int16_t max_block_in_use;
+ uint16_t num_entries;
+ uint16_t max_mlid_ho;
+ uint16_t (*p_mask_tbl)[][IB_MCAST_POSITION_MAX];
+
+} osm_mcast_tbl_t;
+/*
+* FIELDS
+* num_ports
+* The number of ports in the port mask. This value
+* is the same as the number of ports on the switch
+*
+* max_position
+* Maximum bit mask position for this table. This value
+* is computed from the number of ports on the switch.
+*
+* max_block
+* Maximum block number supported in the table. This value
+* is approximately the number of MLID entries divided by the
+* number of MLIDs per block
+*
+* num_entries
+* Number of entries in the table (aka number of MLIDs supported).
+*
+* max_mlid_ho
+* Maximum MLID value (host order).
+*
+* pp_mask_tbl
+* Pointer to a two dimensional array of port_masks for this switch.
+* The first dimension is MLID, the second dimension is mask position.
+* This pointer is null for switches that do not support multicast.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_init
+* NAME
+* osm_mcast_tbl_init
+*
+* DESCRIPTION
+* This function initializes a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_tbl_init(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN uint8_t const num_ports,
+ IN uint16_t const capacity );
+/*
+* PARAMETERS
+* num_ports
+* [in] Number of ports in the switch owning this table.
+*
+* capacity
+* [in] The number of MLID entries (starting at 0xC000) supported
+* by this switch.
+*
+* RETURN VALUE
+* IB_SUCCESS on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_delete
+* NAME
+* osm_mcast_tbl_delete
+*
+* DESCRIPTION
+* This destroys and deallocates a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_delete(
+ IN osm_mcast_tbl_t** const pp_tbl );
+/*
+* PARAMETERS
+* pp_tbl
+* [in] Pointer a Pointer to the Multicast Forwarding Table object.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Multicast Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_destroy
+* NAME
+* osm_mcast_tbl_destroy
+*
+* DESCRIPTION
+* This destroys and deallocates a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_destroy(
+ IN osm_mcast_tbl_t* const p_tbl );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* RETURN VALUE
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set
+* NAME
+* osm_mcast_tbl_set
+*
+* DESCRIPTION
+* Adds the port to the multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_set(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port_num );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* mlid_ho
+* [in] MLID value (host order) for which to set the route.
+*
+* port_num
+* [in] Port to add to the multicast group.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_clear_mlid
+* NAME
+* osm_mcast_tbl_clear_mlid
+*
+* DESCRIPTION
+* Removes all multicast paths for the specified MLID.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_clear_mlid(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* mlid_ho
+* [in] MLID value (host order) for which to clear.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_port
+* NAME
+* osm_mcast_tbl_is_port
+*
+* DESCRIPTION
+* Returns TRUE if the port is in the multicast group.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_is_port(
+ IN const osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port_num );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* mlid_ho
+* [in] MLID value (host order).
+*
+* port_num
+* [in] Port number on the switch
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_any_port
+* NAME
+* osm_mcast_tbl_is_any_port
+*
+* DESCRIPTION
+* Returns TRUE if any port is in the multicast group.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_is_any_port(
+ IN const osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* mlid_ho
+* [in] MLID value (host order).
+*
+* RETURN VALUE
+* Returns TRUE if any port is in the multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set_block
+* NAME
+* osm_mcast_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Multicast Forwarding Table.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_tbl_set_block(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const ib_net16_t* const p_block,
+ IN const int16_t block_num,
+ IN const uint8_t position );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Multicast Forwarding Table object.
+*
+* p_block
+* [in] Pointer to the Forwarding Table block.
+*
+* block_num
+* [in] Block number of this block.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_tbl_block
+* NAME
+* osm_switch_get_mcast_tbl_block
+*
+* DESCRIPTION
+* Retrieve a multicast forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_get_block(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const int16_t block_num,
+ IN const uint8_t position,
+ OUT ib_net16_t* const p_block );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to an osm_mcast_tbl_t object.
+*
+* p_block
+* [in] Pointer to the Forwarding Table block.
+*
+* block_num
+* [in] Block number of this block.
+*
+* p_block
+* [out] Pointer to the 32 entry array to store the
+* forwarding table clock specified by block_id.
+*
+* RETURN VALUES
+* Returns true if there are more blocks necessary to
+* configure all the MLIDs reachable from this switch.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block
+* NAME
+* osm_switch_get_max_block
+*
+* DESCRIPTION
+* Returns the maximum block ID in this table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_mcast_tbl_get_max_block(
+ IN osm_mcast_tbl_t* const p_tbl )
+{
+ return( p_tbl->max_block );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+* Returns the maximum block ID in this table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block
+* NAME
+* osm_switch_get_max_block
+*
+* DESCRIPTION
+* Returns the maximum block ID in use in this table.
+* A value of -1 indicates no blocks are in use.
+*
+* SYNOPSIS
+*/
+static inline int16_t
+osm_mcast_tbl_get_max_block_in_use(
+ IN osm_mcast_tbl_t* const p_tbl )
+{
+ return( p_tbl->max_block_in_use );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+* Returns the maximum block ID in use in this table.
+* A value of -1 indicates no blocks are in use.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_position
+* NAME
+* osm_switch_get_max_position
+*
+* DESCRIPTION
+* Returns the maximum position in this table.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_mcast_tbl_get_max_position(
+ IN osm_mcast_tbl_t* const p_tbl )
+{
+ return( p_tbl->max_position );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+* Returns the maximum position in this table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCAST_TBL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_INFO_H_
+#define _OSM_MCM_INFO_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Multicast Member Info/osm_mcm_info_t
+* NAME
+* osm_mcm_info_t
+*
+* DESCRIPTION
+* Multicast Membership Info object.
+* This object contains information about a nodes membership
+* in a particular multicast group.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcm_info
+{
+ cl_list_item_t list_item;
+ ib_net16_t mlid;
+
+} osm_mcm_info_t;
+/*
+* FIELDS
+* list_item
+* Linkage structure for cl_qlist. MUST BE FIRST MEMBER!
+*
+* mlid
+* MLID of this multicast group.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_construct
+* NAME
+* osm_mcm_info_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Member Info object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mcm_info_construct(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ cl_memclr( p_mcm, sizeof(*p_mcm) );
+}
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a Multicast Member Info object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_destroy
+* NAME
+* osm_mcm_info_destroy
+*
+* DESCRIPTION
+* The osm_mcm_info_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_destroy(
+ IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a Multicast Member Info object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Member Info object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mtree_construct or
+* osm_mtree_init.
+*
+* SEE ALSO
+* Multicast Member Info object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_init
+* NAME
+* osm_mcm_info_init
+*
+* DESCRIPTION
+* Initializes a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_init(
+ IN osm_mcm_info_t* const p_mcm,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to an osm_mcm_info_t object to initialize.
+*
+* mlid
+* [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_new
+* NAME
+* osm_mcm_info_new
+*
+* DESCRIPTION
+* Returns an initialized a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_info_t*
+osm_mcm_info_new(
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* mlid
+* [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+* Pointer to an initialized tree node.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_delete
+* NAME
+* osm_mcm_info_delete
+*
+* DESCRIPTION
+* Destroys and deallocates the specified object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_delete(
+ IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* Pointer to the object to destroy.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCM_INFO_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_mcm_port_t.
+ * This object represents the membership of a port in a multicast group.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_PORT_H_
+#define _OSM_MCM_PORT_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: MCM Port Object/osm_mcm_port_t
+* NAME
+* osm_mcm_port_t
+*
+* DESCRIPTION
+* This object represents a particular port as a member of a
+* multicast group.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcm_port
+{
+ cl_map_item_t map_item;
+ ib_gid_t port_gid;
+ uint8_t scope_state;
+ boolean_t proxy_join;
+
+} osm_mcm_port_t;
+/*
+* FIELDS
+* map_item
+* Map Item for qmap linkage. Must be first element!!
+*
+* port_gid
+* GID of the member port.
+*
+* scope_state
+* ???
+*
+* proxy_join
+* If FALSE - Join was performed by the endport identified by PortGID
+* If TRUE - Join was performed on behalf of the endport identified
+* by PortGID by another port within the same partition
+*
+* SEE ALSO
+* MCM Port Object
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_construct
+* NAME
+* osm_mcm_port_construct
+*
+* DESCRIPTION
+* This function constructs a MCM Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_construct(
+ IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a MCM Port Object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcm_port_init, osm_mcm_port_destroy.
+*
+* Calling osm_mcm_port_construct is a prerequisite to calling any other
+* method except osm_mcm_port_init.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_init, osm_mcm_port_destroy
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+* osm_mcm_port_destroy
+*
+* DESCRIPTION
+* The osm_mcm_port_destroy function destroys a MCM Port Object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_destroy(
+ IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a MCM Port Object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified MCM Port Object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcm_port_construct or osm_mcm_port_init.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+* osm_mcm_port_init
+*
+* DESCRIPTION
+* The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_init(
+ IN osm_mcm_port_t* const p_mcm,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to an osm_mcm_port_t object to initialize.
+*
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* scope_state
+* [in] scope state of the join request
+*
+* proxy_join
+* [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Allows calling other MCM Port Object methods.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+* osm_mcm_port_init
+*
+* DESCRIPTION
+* The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t*
+osm_mcm_port_new(
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* scope_state
+* [in] scope state of the join request
+*
+* proxy_join
+* [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+* Pointer to the allocated and initialized MCM Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+* osm_mcm_port_destroy
+*
+* DESCRIPTION
+* The osm_mcm_port_destroy function destroys and dellallocates an
+* MCM Port Object, releasing all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_delete(
+ IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a MCM Port Object to delete.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCM_PORT_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcmember_t.
+ * This object represents an IBA mcmember.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCMEMBER_H_
+#define _OSM_MCMEMBER_H_
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_qlist.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MCMember
+* NAME
+* MCMember
+*
+* DESCRIPTION
+* The MCMember object encapsulates the information needed by the
+* OpenSM to manage mcmembers. The OpenSM allocates one MCMember object
+* per mcmember in the IBA subnet.
+*
+* The MCMember object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: MCMember/osm_mcmember_t
+* NAME
+* osm_mcmember_t
+*
+* DESCRIPTION
+* MCMember structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmember
+{
+ cl_map_item_t map_item;
+ ib_member_rec_t mcmember_rec;
+ cl_qlist_t mcmember_port_list;
+
+} osm_mcmember_t;
+
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* mcmember_rec
+* The IBA defined MCMemberRecord data for this mcmember.
+*
+* member_port_list
+* List of Port specific information for each port that in
+* member of a MultiCast Group.
+*
+* SEE ALSO
+* MCMember object
+*********/
+
+/****s* OpenSM: MCMember/osm_mcmember_t
+* NAME
+* osm_mcmember_t
+*
+* DESCRIPTION
+* MCMember structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmember_port
+{
+ cl_list_item_t list_item;
+ ib_gid_t port_gid;
+ uint8_t scope_state;
+
+} osm_mcmember_port_t;
+
+/*
+* FIELDS
+* list_item
+* DESCRIPTION???
+*
+* port_gid
+* DESCRIPTION???
+*
+* scope_state
+* description???
+*
+* SEE ALSO
+* MCMember object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMEMBER_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of Dispatcher message values.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_MSGDEF_H_
+#define _OSM_MSGDEF_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Dispatcher Messages
+* NAME
+* Dispatcher Messages
+*
+* DESCRIPTION
+* These constants define the messages sent between OpenSM controllers
+* attached to the Dispatcher.
+*
+* Each message description contains the following information:
+* Sent by: which controller(s) send this message
+* Received by: which controller receives this message
+* Delivery notice: Indicates if the sender requires confirmation
+* that the message has been delivered. Typically a "yes" here
+* means that some resources associated with sending the
+* message must be freed.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_REQ
+* NAME
+* OSM_MSG_REQ
+*
+* DESCRIPTION
+* Initiates a QP0 attribute request.
+*
+* NOTES
+* Sent by: osm_sm_t
+* Received by: osm_req_ctrl_t
+* Delivery notice: yes
+*
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_INFO
+* NAME
+* OSM_MSG_MAD_NODE_INFO
+*
+* DESCRIPTION
+* Message for received NodeInfo MADs.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_ni_rcv_ctrl_t
+* Delivery notice: yes
+*
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_PORT_INFO
+* NAME
+* OSM_MSG_MAD_PORT_INFO
+*
+* DESCRIPTION
+* Message for received PortInfo MADs.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_pi_rcv_ctrl_t
+* Delivery notice: yes
+*
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_SWITCH_INFO
+* NAME
+* OSM_MSG_MAD_SWITCH_INFO
+*
+* DESCRIPTION
+* Message for received SwitchInfo MADs.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_si_rcv_ctrl_t
+* Delivery notice: yes
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_DESC
+* NAME
+* OSM_MSG_MAD_NODE_DESC
+*
+* DESCRIPTION
+* Message for received NodeDescription MADs.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_nd_rcv_ctrl_t
+* Delivery notice: yes
+*
+* SOURCE
+***********/
+/****d* OpenSM: Dispatcher Messages/OSM_MSG_NO_SMPS_OUTSTANDING
+* NAME
+* OSM_MSG_NO_SMPS_OUTSTANDING
+*
+* DESCRIPTION
+* Message indicating that there are no outstanding SMPs on the subnet.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_state_mgr_ctrl_t
+* Delivery notice: no
+*
+* SOURCE
+***********/
+enum
+{
+ OSM_MSG_REQ = 0,
+ OSM_MSG_MAD_NODE_INFO,
+ OSM_MSG_MAD_PORT_INFO,
+ OSM_MSG_MAD_SWITCH_INFO,
+ OSM_MSG_MAD_NODE_DESC,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ OSM_MSG_MAD_NODE_RECORD,
+ OSM_MSG_MAD_PORTINFO_RECORD,
+ OSM_MSG_MAD_SERVICE_RECORD,
+ OSM_MSG_MAD_PATH_RECORD,
+ OSM_MSG_MAD_MCMEMBER_RECORD,
+ OSM_MSG_MAD_LINK_RECORD,
+ OSM_MSG_MAD_SMINFO_RECORD,
+ OSM_MSG_MAD_CLASS_PORT_INFO,
+ OSM_MSG_MAD_INFORM_INFO,
+ OSM_MSG_MAD_LFT_RECORD,
+ OSM_MSG_MAD_LFT,
+ OSM_MSG_MAD_SM_INFO,
+ OSM_MSG_MAD_NOTICE,
+ OSM_MSG_LIGHT_SWEEP_FAIL,
+ OSM_MSG_MAD_MFT,
+ OSM_MSG_MAD_PKEY_TBL_RECORD,
+ OSM_MSG_MAD_VL_ARB_RECORD,
+ OSM_MSG_MAD_SLVL_TBL_RECORD,
+ OSM_MSG_MAD_PKEY,
+ OSM_MSG_MAD_VL_ARB,
+ OSM_MSG_MAD_SLVL,
+ OSM_MSG_MAX
+};
+
+END_C_DECLS
+
+#endif /* _OSM_MSGDEF_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#ifndef _OSM_BIND_H_
+#define _OSM_BIND_H_
+
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_mtl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Vendor/osm_vendor_mgt_bind
+* NAME
+* osm_vendor_mgt_bind_t
+*
+* DESCRIPTION
+* Tracks the handles returned by IB_MGT to the SMI and GSI
+* Nulled on init of the vendor obj. Populated on first bind.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor_mgt_bind
+{
+ boolean_t smi_init, gsi_init;
+ IB_MGT_mad_hndl_t smi_mads_hdl;
+ IB_MGT_mad_hndl_t gsi_mads_hdl;
+ struct _osm_mtl_bind_info *smi_p_bind;
+}
+osm_vendor_mgt_bind_t;
+
+/*
+* FIELDS
+* smi_mads_hdl
+* Handle returned by IB_MGT_get_handle to the IB_MGT_SMI
+*
+* gsi_mads_hdl
+* Handle returned by IB_MGT_get_handle to the IB_MGT_GSI
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor osm_mtl_bind_info_t
+* NAME
+* osm_mtl_bind_info_t
+*
+* DESCRIPTION
+* Handle to the result of binding a class callbacks to IB_MGT.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mtl_bind_info
+{
+ IB_MGT_mad_hndl_t mad_hndl;
+ osm_vendor_t *p_vend;
+ void *client_context;
+ VAPI_hca_hndl_t hca_hndl;
+ VAPI_hca_id_t hca_id;
+ uint8_t port_num;
+ osm_vend_mad_recv_callback_t rcv_callback;
+ osm_vend_mad_send_err_callback_t send_err_callback;
+ osm_mad_pool_t *p_osm_pool;
+}
+osm_mtl_bind_info_t;
+
+/*
+* FIELDS
+* mad_hndl
+* the handle returned from the registration in IB_MGT
+*
+* p_vend
+* Pointer to the vendor object.
+*
+* client_context
+* User's context passed during osm_bind
+*
+* hca_id
+* HCA Id we bind to.
+*
+* port_num
+* Port number (within the HCA) of the bound port.
+*
+* rcv_callback
+* OSM Callback function to be called on receive of MAD.
+*
+* send_err_callback
+* OSM Callback to be called on send error.
+*
+* p_osm_pool
+* Points to the MAD pool used by OSM
+*
+*
+* SEE ALSO
+*********/
+ib_api_status_t
+osm_mtl_send_mad(
+ IN osm_mtl_bind_info_t *p_bind,
+ IN osm_madw_t * const p_madw);
+
+END_C_DECLS
+
+#endif // _OSM_BIND_H_
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mtree_t.
+ * This object represents multicast spanning tree.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MTREE_H_
+#define _OSM_MTREE_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_switch.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_MTREE_LEAF ((void*)-1)
+
+/****h* OpenSM/Multicast Tree
+* NAME
+* Multicast Tree
+*
+* DESCRIPTION
+* The Multicast Tree object encapsulates the information needed by the
+* OpenSM to manage multicast fabric routes. It is a tree structure
+* in which each node in the tree represents a switch, and may have a
+* varying number of children.
+*
+* Multicast trees do not contain loops.
+*
+* The Multicast Tree is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Multicast Tree/osm_mtree_node_t
+* NAME
+* osm_mtree_node_t
+*
+* DESCRIPTION
+* The MTree Node object encapsulates the information needed by the
+* OpenSM for a particular switch in the multicast tree.
+*
+* The MTree Node object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mtree_node
+{
+ cl_map_item_t map_item;
+ osm_switch_t *p_sw;
+ uint8_t max_children;
+ struct _osm_mtree_node *p_up;
+ struct _osm_mtree_node *child_array[1];
+
+} osm_mtree_node_t;
+/*
+* FIELDS
+* map_item
+* Linkage for quick map. MUST BE FIRST ELEMENT!!!
+*
+* p_sw
+* Pointer to the switch represented by this tree node.
+*
+* max_children
+* Maximum number of child nodes of this node. Equal to the
+* the number of ports on the switch if the switch supports
+* multicast. Equal to 1 (default route) if the switch does
+* not support multicast.
+*
+* p_up
+* Pointer to the parent of this node. If this pointer is
+* NULL, the node is at the root of the tree.
+*
+* child_array
+* Array (indexed by port number) of pointers to the
+* child osm_mtree_node_t objects of this tree node, if any.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_construct
+* NAME
+* osm_mtree_node_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Tree Node object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mtree_node_construct(
+ IN osm_mtree_node_t* const p_mtn )
+{
+ cl_memclr( p_mtn, sizeof(*p_mtn) );
+}
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to a Multicast Tree Node object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_destroy
+* NAME
+* osm_mtree_node_destroy
+*
+* DESCRIPTION
+* The osm_mtree_node_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_destroy(
+ IN osm_mtree_node_t* const p_mtn );
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to a Multicast Tree Node object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Tree object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mtree_construct or
+* osm_mtree_init.
+*
+* SEE ALSO
+* Multicast Tree object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_init
+* NAME
+* osm_mtree_node_init
+*
+* DESCRIPTION
+* Initializes a Multicast Tree Node object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_init(
+ IN osm_mtree_node_t* const p_mtn,
+ IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to an osm_mtree_node_t object to initialize.
+*
+* p_sw
+* [in] Pointer to the switch represented by this node.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_new
+* NAME
+* osm_mtree_node_new
+*
+* DESCRIPTION
+* Returns an initialized a Multicast Tree object for use.
+*
+* SYNOPSIS
+*/
+osm_mtree_node_t*
+osm_mtree_node_new(
+ IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch represented by this node.
+*
+* RETURN VALUES
+* Pointer to an initialized tree node.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_destroy
+* NAME
+* osm_mtree_destroy
+*
+* DESCRIPTION
+* Destroys a Multicast Tree object given by the p_mtn
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_destroy(
+ IN osm_mtree_node_t *p_mtn );
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to an osm_mtree_node_t object to destroy.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_max_children
+* NAME
+* osm_mtree_node_get_max_children
+*
+* DESCRIPTION
+* Returns the number maximum number of children of this node.
+* The return value is 1 greater than the highest valid port
+* number on the switch.
+*
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_mtree_node_get_max_children(
+ IN const osm_mtree_node_t* const p_mtn )
+{
+ return( p_mtn->max_children );
+}
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to the multicast tree node.
+*
+* RETURN VALUES
+* See description.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_child
+* NAME
+* osm_mtree_node_get_child
+*
+* DESCRIPTION
+* Returns the specified child node of this node.
+*
+* SYNOPSIS
+*/
+static inline osm_mtree_node_t*
+osm_mtree_node_get_child(
+ IN const osm_mtree_node_t* const p_mtn,
+ IN const uint8_t child )
+{
+ CL_ASSERT( child < p_mtn->max_children );
+ return( p_mtn->child_array[child] );
+}
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to the multicast tree node.
+*
+* child
+* [in] Index of the child to retrieve.
+*
+* RETURN VALUES
+* Returns the specified child node of this node.
+*
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_switch_ptr
+* NAME
+* osm_mtree_node_get_switch_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the switch object represented by this tree node.
+*
+* SYNOPSIS
+*/
+static inline osm_switch_t*
+osm_mtree_node_get_switch_ptr(
+ IN const osm_mtree_node_t* const p_mtn )
+{
+ return( p_mtn->p_sw );
+}
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to the multicast tree node.
+*
+* child
+* [in] Index of the child to retrieve.
+*
+* RETURN VALUES
+* Returns a pointer to the switch object represented by this tree node.
+*
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MTREE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_mgrp_t.
+ * This object represents an IBA Multicast Group.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MULTICAST_H_
+#define _OSM_MULTICAST_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Group
+* NAME
+* Multicast Group
+*
+* DESCRIPTION
+* The Multicast Group encapsulates the information needed by the
+* OpenSM to manage Multicast Groups. The OpenSM allocates one
+* Multicast Group object per Multicast Group in the IBA subnet.
+*
+* The Multicast Group is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****f* IBA Base: OpneSM: Multicast Group/osm_get_mcast_req_type_str
+* NAME
+* osm_get_mcast_req_type_str
+*
+* DESCRIPTION
+* Returns a string for the specified osm_mcast_req_type_t value.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_mcast_req_type_str(
+ IN osm_mcast_req_type_t req_type );
+/*
+* PARAMETERS
+* req_type
+* [in] osm_mcast_req_type value
+*
+* RETURN VALUES
+* Pointer to the request type description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Multicast Group/osm_mcast_mgr_ctxt_t
+* NAME
+* osm_mcast_mgr_ctxt_t
+*
+* DESCRIPTION
+* Struct for passing context arguments to the multicast manager.
+*
+* The osm_mcast_mgr_ctxt_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_mcast_mgr_ctxt
+{
+ ib_net16_t mlid;
+ osm_mcast_req_type_t req_type;
+ ib_net64_t port_guid;
+} osm_mcast_mgr_ctxt_t;
+/*
+* FIELDS
+*
+* mlid
+* The network ordered LID of this Multicast Group (must be >= 0xC000).
+*
+* req_type
+* The type of the request that caused this call
+* (multicast create/join/leave).
+*
+* port_guid
+* The port guid of the port that is being added/removed from
+* the multicast group due to this call.
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Multicast Group/osm_mgrp_t
+* NAME
+* osm_mgrp_t
+*
+* DESCRIPTION
+* Multicast Group structure.
+*
+* The osm_mgrp_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mgrp
+{
+ cl_map_item_t map_item;
+ ib_net16_t mlid;
+ osm_mtree_node_t *p_root;
+ cl_qmap_t mcm_port_tbl;
+ ib_member_rec_t mcmember_rec;
+ boolean_t well_known;
+ boolean_t to_be_deleted;
+ uint32_t last_change_id;
+ uint32_t last_tree_id;
+} osm_mgrp_t;
+/*
+* FIELDS
+* map_item
+* Map Item for qmap linkage. Must be first element!!
+*
+* mlid
+* The network ordered LID of this Multicast Group (must be >= 0xC000).
+*
+* p_root
+* Pointer to the root "tree node" in the single spanning tree
+* for this multicast group. The nodes of the tree represent
+* switches. Member ports are not represented in the tree.
+*
+* mcm_port_tbl
+* Table (sorted by port GUID) of osm_mcm_port_t objects representing
+* the member ports of this multicast group.
+*
+* mcmember_rec
+* Hold the parameters of the Multicast Group.
+*
+* well_known
+* Indicates that this is the wellknow multicast group which is created
+* during the initialization of SM/SA and will be present even if
+* there are no ports for this group
+*
+* to_be_deleted
+* Since groups are deleted only after re-route we need to track the
+* fact the group is about to be deleted so we can track the fact a
+* new join is actually a create request.
+*
+* last_change_id
+* a counter for the number of changes applied to the group.
+* this counter shuold be incremented on any modification to the group:
+* joining or leaving of ports.
+*
+* last_tree_id
+* the last change id used for building the current tree.
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Vendor API/osm_mgrp_func_t
+* NAME
+* osm_mgrp_func_t
+*
+* DESCRIPTION
+* Callback for the osm_mgrp_apply_func function.
+* The callback function must not modify the tree linkage.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_mgrp_func_t)(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const osm_mtree_node_t* const p_mtn,
+ IN void* context );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to the multicast group object.
+*
+* p_mtn
+* [in] Pointer to the multicast tree node.
+*
+* context
+* [in] User context.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_construct
+* NAME
+* osm_mgrp_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_construct(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to a Multicast Group to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mgrp_init, osm_mgrp_destroy.
+*
+* Calling osm_mgrp_construct is a prerequisite to calling any other
+* method except osm_mgrp_init.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_init, osm_mgrp_destroy
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_destroy
+* NAME
+* osm_mgrp_destroy
+*
+* DESCRIPTION
+* The osm_mgrp_destroy function destroys a Multicast Group, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_destroy(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to a Muticast Group to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Group.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mgrp_construct or
+* osm_mgrp_init.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_init
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_init
+* NAME
+* osm_mgrp_init
+*
+* DESCRIPTION
+* The osm_mgrp_init function initializes a Multicast Group for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_init(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object to initialize.
+*
+* mlid
+* [in] Multicast LID for this multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Allows calling other Multicast Group methods.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_new
+* NAME
+* osm_mgrp_new
+*
+* DESCRIPTION
+* Allocates and initializes a Multicast Group for use.
+*
+* SYNOPSIS
+*/
+osm_mgrp_t*
+osm_mgrp_new(
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* mlid
+* [in] Multicast LID for this multicast group.
+*
+* RETURN VALUES
+* IB_SUCCESS if initialization was successful.
+*
+* NOTES
+* Allows calling other Multicast Group methods.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_delete
+* NAME
+* osm_mgrp_delete
+*
+* DESCRIPTION
+* Destroys and de-allocates a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_delete(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_guid
+* NAME
+* osm_mgrp_is_guid
+*
+* DESCRIPTION
+* Indicates if the specified port GUID is a member of the Multicast Group.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_mgrp_is_guid(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid )
+{
+ return( cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid ) !=
+ cl_qmap_end( &p_mgrp->mcm_port_tbl ) );
+}
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* port_guid
+* [in] Port GUID.
+*
+* RETURN VALUES
+* TRUE if the port GUID is a member of the group,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_empty
+* NAME
+* osm_mgrp_is_empty
+*
+* DESCRIPTION
+* Indicates if the multicast group has any member ports.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_mgrp_is_empty(
+ IN const osm_mgrp_t* const p_mgrp )
+{
+ return( cl_qmap_count( &p_mgrp->mcm_port_tbl ) == 0 );
+}
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* TRUE if there are no ports in the multicast group.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_get_mlid
+* NAME
+* osm_mgrp_get_mlid
+*
+* DESCRIPTION
+* The osm_mgrp_get_mlid function returns the multicast LID of this group.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_mgrp_get_mlid(
+ IN const osm_mgrp_t* const p_mgrp )
+{
+ return( p_mgrp->mlid );
+}
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* MLID of the Multicast Group.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_add_port
+* NAME
+* osm_mgrp_add_port
+*
+* DESCRIPTION
+* Adds a port to the multicast group.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t*
+osm_mgrp_add_port(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t join_state,
+ IN boolean_t proxy_join);
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object to initialize.
+*
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* join_state
+* [in] The join state for this port in the group.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Multicast Group/osm_mgrp_is_port_present
+* NAME
+* osm_mgrp_is_port_present
+*
+* DESCRIPTION
+* checks a port from the multicast group.
+*
+* SYNOPSIS
+*/
+
+boolean_t
+osm_mgrp_is_port_present(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid,
+ OUT osm_mcm_port_t ** const pp_mcm_port);
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* port_guid
+* [in] Port guid of the departing port.
+*
+* pp_mcm_port
+* [out] Pointer to a pointer to osm_mcm_port_t
+* Updated to the member on success or NULLed
+*
+* RETURN VALUES
+* TRUE if port present
+* FALSE if port is not present.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+
+/****f* OpenSM: Multicast Group/osm_mgrp_remove_port
+* NAME
+* osm_mgrp_remove_port
+*
+* DESCRIPTION
+* Removes a port from the multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_remove_port(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*
+* p_subn
+* [in] Pointer to the subnet object
+*
+* p_log
+* [in] The log object pointer
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* port_guid
+* [in] Port guid of the departing port.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_get_root_switch
+* NAME
+* osm_mgrp_get_root_switch
+*
+* DESCRIPTION
+* Returns the "root" switch of this multicast group. The root switch
+* is at the trunk of the multicast single spanning tree.
+*
+* SYNOPSIS
+*/
+static inline osm_switch_t*
+osm_mgrp_get_root_switch(
+ IN const osm_mgrp_t* const p_mgrp )
+{
+ if( p_mgrp->p_root )
+ return( p_mgrp->p_root->p_sw );
+ else
+ return( NULL );
+}
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* Returns the "root" switch of this multicast group. The root switch
+* is at the trunk of the multicast single spanning tree.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_compute_avg_hops
+* NAME
+* osm_mgrp_compute_avg_hops
+*
+* DESCRIPTION
+* Returns the average number of hops from the given to switch
+* to all member of a multicast group.
+*
+* SYNOPSIS
+*/
+float
+osm_mgrp_compute_avg_hops(
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* p_sw
+* [in] Pointer to the switch from which to measure.
+*
+* RETURN VALUES
+* Returns the average number of hops from the given to switch
+* to all member of a multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_apply_func
+* NAME
+* osm_mgrp_apply_func
+*
+* DESCRIPTION
+* Calls the specified function for each element in the tree.
+* Elements are passed to the callback function in no particular order.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_apply_func(
+ const osm_mgrp_t* const p_mgrp,
+ osm_mgrp_func_t p_func,
+ void* context );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* p_func
+* [in] Pointer to the users callback function.
+*
+* context
+* [in] User context passed to the callback function.
+*
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_delete_notice
+* NAME
+* osm_mgrp_send_delete_notice
+*
+* DESCRIPTION
+* Sends a notice that the given multicast group is now deleted.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_delete_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_create_notice
+* NAME
+* osm_mgrp_send_create_notice
+*
+* DESCRIPTION
+* Sends a notice that the given multicast group is now created.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_create_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MULTICAST_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_node_t.
+ * This object represents an IBA node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NODE_H_
+#define _OSM_NODE_H_
+
+#include <complib/cl_qmap.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_madw.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node
+* NAME
+* Node
+*
+* DESCRIPTION
+* The Node object encapsulates the information needed by the
+* OpenSM to manage nodes. The OpenSM allocates one Node object
+* per node in the IBA subnet.
+*
+* The Node object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node/osm_node_t
+* NAME
+* osm_node_t
+*
+* DESCRIPTION
+* Node structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_node
+{
+ cl_map_item_t map_item;
+ ib_node_info_t node_info;
+ ib_node_desc_t node_desc;
+ uint32_t discovery_count;
+ uint32_t physp_tbl_size;
+ osm_physp_t physp_table[1];
+
+} osm_node_t;
+
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* node_info
+* The IBA defined NodeInfo data for this node.
+*
+* node_desc
+* The IBA defined NodeDescription data for this node.
+*
+* discovery_count
+* The number of times this node has been discovered
+* during the current fabric sweep. This number is reset
+* to zero at the start of a sweep.
+*
+* phsyp_tbl_size
+* The size of the physp_table array. This value is one greater
+* than the number of ports in the node, since port numbers
+* start with 1 for some bizzare reason.
+*
+* phsyp_table
+* Array of physical port objects belonging to this node.
+* Index is contiguous by local port number.
+* For switches, port 0 is the always the managment port. (14.2.5.6)
+* MUST BE LAST MEMBER! - Since it Grows !!!!
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_destroy
+* NAME
+* osm_node_destroy
+*
+* DESCRIPTION
+* The osm_node_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/void
+osm_node_destroy(
+ IN osm_node_t *p_node );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer a Node object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Node object.
+* This function should only be called after a call to osm_node_new.
+*
+* SEE ALSO
+* Node object, osm_node_new
+*********/
+
+/****f* OpenSM: Node/osm_node_delete
+* NAME
+* osm_node_delete
+*
+* DESCRIPTION
+* The osm_node_delete function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_node_delete(
+ IN OUT osm_node_t** const p_node );
+/*
+* PARAMETERS
+* p_node
+* [in][out] Pointer to a Pointer a Node object to destroy.
+* On return, the pointer to set to NULL.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Node object.
+* This function should only be called after a call to osm_node_new.
+*
+* SEE ALSO
+* Node object, osm_node_new
+*********/
+
+/****f* OpenSM: Node/osm_node_new
+* NAME
+* osm_node_new
+*
+* DESCRIPTION
+* The osm_node_new function initializes a Node object for use.
+*
+* SYNOPSIS
+*/
+osm_node_t*
+osm_node_new(
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to a osm_madw_t object containing a mad with
+* the node's NodeInfo attribute. The caller may discard the
+* osm_madw_t structure after calling osm_node_new.
+*
+* RETURN VALUES
+* On success, a pointer to the new initialized osm_node_t structure.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_is_lid
+* NAME
+* osm_node_is_lid
+*
+* DESCRIPTION
+* Indicates if the specified LID belongs to this node.
+*
+* SYNOPSIS
+*/
+boolean_t osm_node_is_lid(
+ IN const osm_node_t* const p_node,
+ IN const uint16_t lid );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* lid
+* [in] LID value.
+*
+* RETURN VALUES
+* TRUE if the specified LID belongs to the node,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_physp_ptr
+* NAME
+* osm_node_get_physp_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_node_get_physp_ptr(
+ IN const osm_node_t* const p_node,
+ IN const uint32_t port_num )
+{
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ return( (osm_physp_t*)&p_node->physp_table[port_num] );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns a pointer to the physical port object at the
+* specified local port number.
+* A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_node_get_any_physp_ptr
+* NAME
+* osm_node_get_any_physp_ptr
+*
+* DESCRIPTION
+* Returns a pointer to any valid physical port object associated
+* with this node. This operation is mostly meaningful for switches,
+* in which case all the Physical Ports share the same GUID.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_node_get_any_physp_ptr(
+ IN const osm_node_t* const p_node )
+{
+ CL_ASSERT( p_node );
+ return( (osm_physp_t*)&p_node->physp_table[
+ ib_node_info_get_local_port_num( &p_node->node_info )] );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns a pointer to any valid physical port object associated
+* with this node. This operation is mostly meaningful for switches,
+* in which case all the Physical Ports share the same GUID.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_any_path
+* NAME
+* osm_node_get_any_path
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_dr_path_t*
+osm_node_get_any_dr_path_ptr(
+ IN const osm_node_t* const p_node )
+{
+ CL_ASSERT( p_node );
+ return( osm_physp_get_dr_path_ptr( &p_node->physp_table[
+ ib_node_info_get_local_port_num( &p_node->node_info )] ) );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns a pointer to the physical port object at the
+* specified local port number.
+* A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_type
+* NAME
+* osm_node_get_type
+*
+* DESCRIPTION
+* Returns the type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_type(
+ IN const osm_node_t* const p_node )
+{
+ return( p_node->node_info.node_type );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns the IBA defined type of this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_node_get_num_physp
+* NAME
+* osm_node_get_num_physp
+*
+* DESCRIPTION
+* Returns the type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_num_physp(
+ IN const osm_node_t* const p_node )
+{
+ return( (uint8_t)p_node->physp_tbl_size );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns the IBA defined type of this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_node
+* NAME
+* osm_node_get_remote_node
+*
+* DESCRIPTION
+* Returns a pointer to the node on the other end of the
+* specified port.
+* Returns NULL if no remote node exists.
+*
+* SYNOPSIS
+*/
+osm_node_t*
+osm_node_get_remote_node(
+ IN const osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ OUT uint8_t *p_remote_port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to get the remote node.
+*
+* p_remote_port_num
+* [out] Port number in the remote's node through which this
+* link exists. The caller may specify NULL for this pointer
+* if the port number isn't needed.
+*
+* RETURN VALUES
+* Returns a pointer to the node on the other end of the
+* specified port.
+* Returns NULL if no remote node exists.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_base_lid
+* NAME
+* osm_node_get_base_lid
+*
+* DESCRIPTION
+* Returns the LID value of the specified port on this node.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_node_get_base_lid(
+ IN const osm_node_t* const p_node,
+ IN const uint32_t port_num )
+{
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ return( osm_physp_get_base_lid( &p_node->physp_table[port_num] ) );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns a pointer to the physical port object at the
+* specified local port number.
+* A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_base_lid
+* NAME
+* osm_node_get_remote_base_lid
+*
+* DESCRIPTION
+* Returns the base LID value of the port on the other side
+* of the wire from the specified port on this node.
+*
+* SYNOPSIS
+*/
+ib_net16_t
+osm_node_get_remote_base_lid(
+ IN const osm_node_t* const p_node,
+ IN const uint32_t port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns a pointer to the physical port object at the
+* specified local port number.
+* A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_type
+* NAME
+* osm_node_get_remote_type
+*
+* DESCRIPTION
+* Returns the type of the node on the other side
+* of the wire from the specified port on this node.
+* The remote node must exist.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_remote_type(
+ IN const osm_node_t* const p_node,
+ IN const uint8_t port_num )
+{
+ osm_node_t *p_remote_node;
+
+ p_remote_node = osm_node_get_remote_node( p_node, port_num, NULL );
+ CL_ASSERT( p_remote_node );
+ return( osm_node_get_type( p_remote_node ) );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns the type of the node on the other side
+* of the wire from the specified port on this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_lmc
+* NAME
+* osm_node_get_lmc
+*
+* DESCRIPTION
+* Returns the LMC value of the specified port on this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_lmc(
+ IN const osm_node_t* const p_node,
+ IN const uint32_t port_num )
+{
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ return( osm_physp_get_lmc( &p_node->physp_table[port_num] ) );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns the LMC value of the specified port on this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_init_physp
+* NAME
+* osm_node_init_physp
+*
+* DESCRIPTION
+* Initializes a physical port for the given node.
+*
+* SYNOPSIS
+*/
+void
+osm_node_init_physp(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* p_madw
+* [in] Pointer to a osm_madw_t object containing a mad with
+* the node's NodeInfo attribute as discovered through the
+* Physical Port to add to the node. The caller may discard the
+* osm_madw_t structure after calling osm_node_new.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object, Physical Port object.
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_get
+* NAME
+* osm_node_discovery_count_get
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_node_discovery_count_get(
+ IN const osm_node_t* const p_node )
+{
+ return( p_node->discovery_count );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_node_discovery_count_reset
+* NAME
+* osm_node_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this node to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_reset(
+ IN osm_node_t* const p_node )
+{
+ p_node->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_node_discovery_count_inc
+* NAME
+* osm_node_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_inc(
+ IN osm_node_t* const p_node )
+{
+ p_node->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_node_guid
+* NAME
+* osm_node_get_node_guid
+*
+* DESCRIPTION
+* Returns the node GUID of this node.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_node_get_node_guid(
+ IN const osm_node_t* const p_node )
+{
+ return( p_node->node_info.node_guid );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns the node GUID of this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link
+* NAME
+* osm_node_link
+*
+* DESCRIPTION
+* Logically connects a node to another node through the specified port.
+*
+* SYNOPSIS
+*/
+void
+osm_node_link(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to create the link.
+*
+* p_remote_node
+* [in] Pointer to the remote port object.
+*
+* remote_port_num
+* [in] Port number in the remote's node through which to
+* create this link.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_node_unlink
+* NAME
+* osm_node_unlink
+*
+* DESCRIPTION
+* Logically disconnects a node from another node through
+* the specified port.
+*
+* SYNOPSIS
+*/
+void
+osm_node_unlink(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to unlink.
+*
+* p_remote_node
+* [in] Pointer to the remote port object.
+*
+* remote_port_num
+* [in] Port number in the remote's node through which to unlink.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link_exists
+* NAME
+* osm_node_link_exists
+*
+* DESCRIPTION
+* Return TRUE if a link exists between the specified nodes on
+* the specified ports.
+* Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_link_exists(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to check the link.
+*
+* p_remote_node
+* [in] Pointer to the remote port object.
+*
+* remote_port_num
+* [in] Port number in the remote's node through which to
+* check this link.
+*
+* RETURN VALUES
+* Return TRUE if a link exists between the specified nodes on
+* the specified ports.
+* Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_has_any_link
+* NAME
+* osm_node_has_any_link
+*
+* DESCRIPTION
+* Return TRUE if a any link exists from the specified nodes on
+* the specified port.
+* Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_has_any_link(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to check the link.
+*
+* RETURN VALUES
+* Return TRUE if a any link exists from the specified nodes on
+* the specified port.
+* Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link_has_valid_ports
+* NAME
+* osm_node_link_has_valid_ports
+*
+* DESCRIPTION
+* Return TRUE if both ports in the link are valid (initialized).
+* Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_link_has_valid_ports(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Port number in p_node through which to check the link.
+*
+* RETURN VALUES
+* Return TRUE if both ports in the link are valid (initialized).
+* Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NODE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nd_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_ND_RCV_H_
+#define _OSM_ND_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Description Receiver
+* NAME
+* Node Description Receiver
+*
+* DESCRIPTION
+* The Node Description Receiver object encapsulates the information
+* needed to receive the NodeInfo attribute from a node.
+*
+* The Node Description Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Node Description Receiver/osm_nd_rcv_t
+* NAME
+* osm_nd_rcv_t
+*
+* DESCRIPTION
+* Node Description Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_nd_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Node Description Receiver object
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_construct
+* NAME
+* osm_nd_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Description Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_construct(
+ IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Node Description Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nd_rcv_init, osm_nd_rcv_destroy
+*
+* Calling osm_nd_rcv_construct is a prerequisite to calling any other
+* method except osm_nd_rcv_init.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_init,
+* osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_destroy
+* NAME
+* osm_nd_rcv_destroy
+*
+* DESCRIPTION
+* The osm_nd_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_destroy(
+ IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Description Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nd_rcv_construct or osm_nd_rcv_init.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_construct,
+* osm_nd_rcv_init
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_init
+* NAME
+* osm_nd_rcv_init
+*
+* DESCRIPTION
+* The osm_nd_rcv_init function initializes a
+* Node Description Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nd_rcv_init(
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Description Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Description Receiver methods.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_construct,
+* osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_process
+* NAME
+* osm_nd_rcv_process
+*
+* DESCRIPTION
+* Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_process(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+* This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+* Node Description Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_ND_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nd_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeDescription
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ND_RCV_CTRL_H_
+#define _OSM_ND_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Description Receive Controller
+* NAME
+* Node Description Receive Controller
+*
+* DESCRIPTION
+* The Node Description Receive Controller object encapsulates the information
+* needed to receive the NodeDescription attribute from a node.
+*
+* The Node Description Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_t
+* NAME
+* osm_nd_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Description Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv_ctrl
+{
+ osm_nd_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_nd_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Description Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Description Receive Controller object
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_construct
+* NAME
+* osm_nd_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Description Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_construct(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Description Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nd_rcv_ctrl_init, osm_nd_rcv_ctrl_destroy
+*
+* Calling osm_nd_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_init,
+* osm_nd_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_destroy
+* NAME
+* osm_nd_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_nd_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_destroy(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Description Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nd_rcv_ctrl_construct or osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+* osm_nd_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_init
+* NAME
+* osm_nd_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_nd_rcv_ctrl_init function initializes a
+* Node Description Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl,
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_nd_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Description Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Description Receive Controller methods.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+* osm_nd_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_ND_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_NI_RCV_H_
+#define _OSM_NI_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receiver
+* NAME
+* Node Info Receiver
+*
+* DESCRIPTION
+* The Node Info Receiver object encapsulates the information
+* needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receiver/osm_ni_rcv_t
+* NAME
+* osm_ni_rcv_t
+*
+* DESCRIPTION
+* Node Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_gen_req;
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_ni_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_construct
+* NAME
+* osm_ni_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_construct(
+ IN osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_ni_rcv_init, osm_ni_rcv_destroy,
+* and osm_ni_rcv_is_inited.
+*
+* Calling osm_ni_rcv_construct is a prerequisite to calling any other
+* method except osm_ni_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_init,
+* osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_destroy
+* NAME
+* osm_ni_rcv_destroy
+*
+* DESCRIPTION
+* The osm_ni_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_destroy(
+ IN osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ni_rcv_construct or osm_ni_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_init
+* NAME
+* osm_ni_rcv_init
+*
+* DESCRIPTION
+* The osm_ni_rcv_init function initializes a
+* Node Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_init(
+ IN osm_ni_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_is_inited
+* NAME
+* osm_ni_rcv_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_ni_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_is_inited(
+ IN const osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_ni_rcv_construct or osm_ni_rcv_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_process
+* NAME
+* osm_ni_rcv_process
+*
+* DESCRIPTION
+* Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_process(
+ IN const osm_ni_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+* This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+* Node Info Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ni_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_NI_RCV_CTRL_H_
+#define _OSM_NI_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node_info_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receive Controller
+* NAME
+* Node Info Receive Controller
+*
+* DESCRIPTION
+* The Node Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_t
+* NAME
+* osm_ni_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv_ctrl
+{
+ osm_ni_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_ni_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Info Receive Controller object
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_construct
+* NAME
+* osm_ni_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_construct(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_ni_rcv_ctrl_init, osm_ni_rcv_ctrl_destroy,
+* and osm_ni_rcv_ctrl_is_inited.
+*
+* Calling osm_ni_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_init,
+* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_destroy
+* NAME
+* osm_ni_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_ni_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_destroy(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_init
+* NAME
+* osm_ni_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_ni_rcv_ctrl_init function initializes a
+* Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_ctrl_init(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl,
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_is_inited
+* NAME
+* osm_ni_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_ni_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_ctrl_is_inited(
+ IN const osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_opensm_t.
+ * This object represents the OpenSM super object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_OPENSM_H_
+#define _OSM_OPENSM_H_
+
+#include <signal.h>
+#include <opensm/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_atomic.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_ucast_updn.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/OpenSM
+* NAME
+* OpenSM
+*
+* DESCRIPTION
+* The OpenSM object encapsulates the information needed by the
+* OpenSM to govern itself. The OpenSM is one OpenSM object.
+*
+* The OpenSM object is thread safe.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: OpenSM/osm_opensm_t
+* NAME
+* osm_opensm_t
+*
+* DESCRIPTION
+* OpenSM structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_opensm_t
+{
+ osm_subn_t subn;
+ osm_sm_t sm;
+ osm_sa_t sa;
+ osm_db_t db;
+ osm_mad_pool_t mad_pool;
+ osm_vendor_t *p_vendor;
+ osm_vl15_t vl15;
+ osm_log_t log;
+ cl_dispatcher_t disp;
+ cl_plock_t lock;
+ updn_t *p_updn_ucast_routing;
+ osm_stats_t stats;
+} osm_opensm_t;
+/*
+* FIELDS
+* subn
+* Subnet object for this subnet.
+*
+* sm
+* The Subnet Manger (SM) object for this subnet.
+*
+* sa
+* The Subnet Administrator (SA) object for this subnet.
+*
+* db
+* Persistant storage of some data required between sessions.
+*
+* mad_pool
+* Pool of Management Datagram (MAD) objects.
+*
+* p_vendor
+* Pointer to the Vendor specific adapter for various
+* transport interfaces, such as UMADT, AL, etc. The
+* particular interface is set at compile time.
+*
+* vl15
+* The VL15 interface.
+*
+* log
+* Log facility used by all OpenSM components.
+*
+* disp
+* Central dispatcher containing the OpenSM worker threads.
+*
+* lock
+* Shared lock guarding most OpenSM structures.
+*
+* stats
+* Open SM statistics block
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_construct
+* NAME
+* osm_opensm_construct
+*
+* DESCRIPTION
+* This function constructs an OpenSM object.
+*
+* SYNOPSIS
+*/
+void osm_opensm_construct(
+ IN osm_opensm_t* const p_osm );
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to a OpenSM object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_opensm_init, osm_opensm_destroy
+*
+* Calling osm_opensm_construct is a prerequisite to calling any other
+* method except osm_opensm_init.
+*
+* SEE ALSO
+* SM object, osm_opensm_init, osm_opensm_destroy
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_destroy
+* NAME
+* osm_opensm_destroy
+*
+* DESCRIPTION
+* The osm_opensm_destroy function destroys an SM, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_opensm_destroy(
+ IN osm_opensm_t* const p_osm );
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to a OpenSM object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified OpenSM object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_opensm_construct or
+* osm_opensm_init.
+*
+* SEE ALSO
+* SM object, osm_opensm_construct, osm_opensm_init
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_init
+* NAME
+* osm_opensm_init
+*
+* DESCRIPTION
+* The osm_opensm_init function initializes a OpenSM object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_opensm_init(
+ IN osm_opensm_t* const p_osm,
+ IN const osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object to initialize.
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* IB_SUCCESS if the OpenSM object was initialized successfully.
+*
+* NOTES
+* Allows calling other OpenSM methods.
+*
+* SEE ALSO
+* SM object, osm_opensm_construct, osm_opensm_destroy
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_sweep
+* NAME
+* osm_opensm_sweep
+*
+* DESCRIPTION
+* Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_opensm_sweep(
+ IN osm_opensm_t* const p_osm )
+{
+ osm_sm_sweep( &p_osm->sm );
+}
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object on which to
+* initiate a sweep.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* If the OpenSM object is not bound to a port, this function
+* does nothing.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_set_log_flags
+* NAME
+* osm_opensm_set_log_flags
+*
+* DESCRIPTION
+* Sets the log level.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_opensm_set_log_flags(
+ IN osm_opensm_t* const p_osm,
+ IN const osm_log_level_t log_flags )
+{
+ osm_log_set_level( &p_osm->log, log_flags );
+}
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* log_flags
+* [in] Log level flags to set.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_bind
+* NAME
+* osm_opensm_bind
+*
+* DESCRIPTION
+* Binds the opensm object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_opensm_bind(
+ IN osm_opensm_t* const p_osm,
+ IN const ib_net64_t guid );
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object to bind.
+*
+* guid
+* [in] Local port GUID with which to bind.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given opensm object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_wait_for_subnet_up
+* NAME
+* osm_opensm_wait_for_subnet_up
+*
+* DESCRIPTION
+* Blocks the calling thread until the subnet is up.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_opensm_wait_for_subnet_up(
+ IN osm_opensm_t* const p_osm,
+ IN uint32_t const wait_us,
+ IN boolean_t const interruptible )
+{
+ return( osm_sm_wait_for_subnet_up( &p_osm->sm, wait_us, interruptible ) );
+}
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* wait_us
+* [in] Number of microseconds to wait.
+*
+* interruptible
+* [in] Indicates whether the wait operation can be interrupted
+* by external signals.
+*
+* RETURN VALUES
+* CL_SUCCESS if the wait operation succeeded in response to the event
+* being set.
+*
+* CL_TIMEOUT if the specified time period elapses.
+*
+* CL_NOT_DONE if the wait was interrupted by an external signal.
+*
+* CL_ERROR if the wait operation failed.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****v* OpenSM/osm_exit_flag
+*/
+extern volatile int osm_exit_flag;
+/*
+* DESCRIPTION
+* Set to one to cause all threads to leave
+*********/
+
+#ifndef __WIN__
+/****f* OpenSM: OpenSM/osm_reg_sig_handler
+* NAME
+* osm_reg_sig_handler
+*
+* DESCRIPTION
+* Registers the common signal handler
+*
+* SYNOPSIS
+*/
+void osm_reg_sig_handler(
+IN osm_opensm_t* const p_osm);
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to a OpenSM object to handle signals on.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+#endif
+
+END_C_DECLS
+
+#endif /* _OSM_OPENSM_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_prtn_t.
+ * This object represents an IBA Partition.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PARTITION_H_
+#define _OSM_PARTITION_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Partition
+* NAME
+* Partition
+*
+* DESCRIPTION
+* The Partition object encapsulates the information needed by the
+* OpenSM to manage Partitions. The OpenSM allocates one Partition
+* object per Partition in the IBA subnet.
+*
+* The Partition is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Partition/osm_prtn_t
+* NAME
+* osm_prtn_t
+*
+* DESCRIPTION
+* Partition structure.
+*
+* The osm_prtn_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_prtn
+{
+ uint16_t pkey;
+ cl_map port_guid_tbl;
+
+} osm_prtn_t;
+/*
+* FIELDS
+* pkey
+* The IBA defined P_KEY of this Partition.
+*
+* port_guid_tbl
+* Container of pointers to all Port objects in the Partition,
+* indexed by port GUID.
+*
+* SEE ALSO
+* Partition
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_construct
+* NAME
+* osm_prtn_construct
+*
+* DESCRIPTION
+* This function constructs a Partition.
+*
+* SYNOPSIS
+*/
+void osm_prtn_construct(
+ IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to a Partition to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_prtn_init, osm_prtn_destroy, and osm_prtn_is_inited.
+*
+* Calling osm_prtn_construct is a prerequisite to calling any other
+* method except osm_prtn_init.
+*
+* SEE ALSO
+* Partition, osm_prtn_init, osm_prtn_destroy, osm_prtn_is_inited
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_destroy
+* NAME
+* osm_prtn_destroy
+*
+* DESCRIPTION
+* The osm_prtn_destroy function destroys a Partition, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_prtn_destroy(
+ IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to a Partition to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Partition.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_prtn_construct or
+* osm_prtn_init.
+*
+* SEE ALSO
+* Partition, osm_prtn_construct, osm_prtn_init
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_init
+* NAME
+* osm_prtn_init
+*
+* DESCRIPTION
+* The osm_prtn_init function initializes a Partition for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_prtn_init(
+ IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to an osm_prtn_t object to initialize.
+*
+* RETURN VALUES
+* CL_SUCCESS if initialization was successful.
+*
+* NOTES
+* Allows calling other Partition methods.
+*
+* SEE ALSO
+* Partition, osm_prtn_construct, osm_prtn_destroy,
+* osm_prtn_is_inited
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_is_inited
+* NAME
+* osm_prtn_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_prtn_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ptrn_is_inited(
+ IN const osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to an osm_prtn_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_prtn_construct or osm_prtn_init must be called before using
+* this function.
+*
+* SEE ALSO
+* Partition, osm_prtn_construct, osm_prtn_init
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_is_guid
+* NAME
+* osm_prtn_is_guid
+*
+* DESCRIPTION
+* Indicates if a port is a member of the partition.
+*
+* SYNOPSIS
+*/
+boolean_t osm_prtn_is_guid(
+ IN const osm_prtn_t* const p_prtn,
+ IN const uint64 guid );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to an osm_prtn_t object.
+*
+* guid
+* [in] Port GUID.
+*
+* RETURN VALUES
+* TRUE if the specified port GUID is a member of the partition,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_get_pkey
+* NAME
+* osm_prtn_get_pkey
+*
+* DESCRIPTION
+* Gets the IBA defined P_KEY value for this Partition.
+*
+* SYNOPSIS
+*/
+uint16_t osm_prtn_get_pkey(
+ IN const osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+* p_prtn
+* [in] Pointer to an osm_prtn_t object.
+*
+* RETURN VALUES
+* P_KEY value for this Partition.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PARTITION_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_PATH_H_
+#define _OSM_PATH_H_
+
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ * Declaration of path related objects.
+ * These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****h* OpenSM/DR Path
+* NAME
+* DR Path
+*
+* DESCRIPTION
+* The DR Path structure encapsulates a directed route through the subnet.
+*
+* This structure allows direct access to member variables.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: DR Path/osm_dr_path_t
+* NAME
+* osm_dr_path_t
+*
+* DESCRIPTION
+* Directed Route structure.
+*
+* This structure allows direct access to member variables.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_dr_path
+{
+ osm_bind_handle_t h_bind;
+ uint8_t hop_count;
+ uint8_t path[IB_SUBNET_PATH_HOPS_MAX];
+
+} osm_dr_path_t;
+/*
+* FIELDS
+* h_bind
+* Bind handle for port to which this path applies.
+*
+* hop_count
+* The number of hops in this path.
+*
+* path
+* The array of port numbers that comprise this path.
+*
+* SEE ALSO
+* DR Path structure
+*********/
+/****f* OpenSM: DR Path/osm_dr_path_construct
+* NAME
+* osm_dr_path_construct
+*
+* DESCRIPTION
+* This function constructs a directed route path object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_construct(
+ IN osm_dr_path_t* const p_path )
+{
+ /* The first location in the path array is reserved. */
+ cl_memclr( p_path, sizeof(*p_path) );
+ p_path->h_bind = OSM_BIND_INVALID_HANDLE;
+}
+
+/*
+* PARAMETERS
+* p_path
+* [in] Pointer to a directed route path oject to initialize.
+*
+* h_bind
+* [in] Bind handle for the port on which this path applies.
+*
+* hop_count
+* [in] Hop count needed to reach this node.
+*
+* path
+* [in] Directed route path to reach this node.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: DR Path/osm_dr_path_init
+* NAME
+* osm_dr_path_init
+*
+* DESCRIPTION
+* This function initializes a directed route path object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_init(
+ IN osm_dr_path_t* const p_path,
+ IN const osm_bind_handle_t h_bind,
+ IN const uint8_t hop_count,
+ IN const uint8_t path[IB_SUBNET_PATH_HOPS_MAX] )
+{
+ /* The first location in the path array is reserved. */
+ CL_ASSERT( path[0] == 0 );
+ CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );
+ p_path->h_bind = h_bind;
+ p_path->hop_count = hop_count;
+ cl_memcpy( p_path->path, path, IB_SUBNET_PATH_HOPS_MAX );
+}
+
+/*
+* PARAMETERS
+* p_path
+* [in] Pointer to a directed route path oject to initialize.
+*
+* h_bind
+* [in] Bind handle for the port on which this path applies.
+*
+* hop_count
+* [in] Hop count needed to reach this node.
+*
+* path
+* [in] Directed route path to reach this node.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: DR Path/osm_dr_path_extend
+* NAME
+* osm_dr_path_extend
+*
+* DESCRIPTION
+* Adds a new hop to a path.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_extend(
+ IN osm_dr_path_t* const p_path,
+ IN const uint8_t port_num )
+{
+ p_path->hop_count++;
+ CL_ASSERT( p_path->hop_count < IB_SUBNET_PATH_HOPS_MAX );
+ /*
+ Location 0 in the path array is reserved per IB spec.
+ */
+ p_path->path[p_path->hop_count] = port_num;
+}
+
+/*
+* PARAMETERS
+* p_path
+* [in] Pointer to a directed route path oject to initialize.
+*
+* port_num
+* [in] Additional port to add to the DR path.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: DR Path/osm_dr_path_get_bind_handle
+* NAME
+* osm_dr_path_get_bind_handle
+*
+* DESCRIPTION
+* Gets the bind handle from a path.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_dr_path_get_bind_handle(
+ IN const osm_dr_path_t* const p_path )
+{
+ return( p_path->h_bind );
+}
+
+/*
+* PARAMETERS
+* p_path
+* [in] Pointer to a directed route path oject to initialize.
+*
+* port_num
+* [in] Additional port to add to the DR path.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PATH_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_conf_ctrl_t.
+ * This object represents a controller that performs a
+ * Set(PortInfo) for the specified port.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_CONFIG_CTRL_H_
+#define _OSM_PI_CONFIG_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Info Configuration Controller
+* NAME
+* Port Info Configuration Controller
+*
+* DESCRIPTION
+* The Port Info Configuration Controller object encapsulates the
+* information needed to Set(PortInfo) at the specified port.
+*
+* The Port Info Configuration Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_t
+* NAME
+* osm_pi_conf_ctrl_t
+*
+* DESCRIPTION
+* Port Info Configuration Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_conf_ctrl
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_pi_conf_ctrl_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* Port Info Configuration Controller object
+*********/
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_construct
+* NAME
+* osm_pi_conf_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Port Info Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pi_conf_ctrl_construct(
+ IN osm_pi_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Port Info Configuration Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pi_conf_ctrl_init, osm_pi_conf_ctrl_destroy,
+* and osm_pi_conf_ctrl_is_inited.
+*
+* Calling osm_pi_conf_ctrl_construct is a prerequisite to calling any other
+* method except osm_pi_conf_ctrl_init.
+*
+* SEE ALSO
+* Port Info Configuration Controller object, osm_pi_conf_ctrl_init,
+* osm_pi_conf_ctrl_destroy, osm_pi_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_destroy
+* NAME
+* osm_pi_conf_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pi_conf_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_conf_ctrl_destroy(
+ IN osm_pi_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Port Info Configuration Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pi_conf_ctrl_construct or osm_pi_conf_ctrl_init.
+*
+* SEE ALSO
+* Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+* osm_pi_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_init
+* NAME
+* osm_pi_conf_ctrl_init
+*
+* DESCRIPTION
+* The osm_pi_conf_ctrl_init function initializes a
+* Port Info Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_conf_ctrl_init(
+ IN osm_pi_conf_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_conf_ctrl_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Port Info Configuration Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Port Info Configuration Controller methods.
+*
+* SEE ALSO
+* Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+* osm_pi_conf_ctrl_destroy, osm_pi_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_is_inited
+* NAME
+* osm_pi_conf_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pi_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pi_conf_ctrl_is_inited(
+ IN const osm_pi_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_conf_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pi_conf_ctrl_construct or osm_pi_conf_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+* osm_pi_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_process
+* NAME
+* osm_pi_conf_ctrl_process
+*
+* DESCRIPTION
+* Initiate a PortInfo configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_conf_ctrl_process(
+ IN const osm_pi_conf_ctrl_t* const p_ctrl,
+ IN const ib_guid_t guid );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_conf_ctrl_t object.
+*
+* guid
+* [in] GUID of port to configure.
+*
+* RETURN VALUES
+* CL_SUCCESS if configuration processing was successfully
+* initiated.
+*
+* NOTES
+* A success status here does not indicate that
+* the PortInfo configuration process completed successfully.
+*
+* SEE ALSO
+* Port Info Configuration Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_CONFIG_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#ifndef _OSM_PKEY_H_
+#define _OSM_PKEY_H_
+
+#include <iba/ib_types.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_req.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ Forward references.
+*/
+struct _osm_physp;
+struct _osm_port;
+struct _osm_subn;
+struct _osm_node;
+struct _osm_physp;
+
+/*
+ * Abstract:
+ * Declaration of pkey manipulation functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+/****s* OpenSM: osm_pkey_tbl_t
+* NAME
+* osm_pkey_tbl_t
+*
+* DESCRIPTION
+* This object represents a pkey table. The need for a special object
+* is required to optimize search performance of a PKey in the IB standard
+* non sorted table.
+*
+* The osm_pkey_tbl_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_tbl
+{
+ cl_ptr_vector_t blocks;
+ cl_map_t keys;
+} osm_pkey_tbl_t;
+/*
+* FIELDS
+* blocks
+* The IBA defined blocks of pkey values
+*
+* keys
+* A set holding all keys
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_construct
+* NAME
+* osm_pkey_tbl_construct
+*
+* DESCRIPTION
+* Constructs the PKey table object
+*
+* SYNOPSIS
+*/
+void osm_pkey_tbl_construct(
+ IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_init
+* NAME
+* osm_pkey_tbl_init
+*
+* DESCRIPTION
+* Inits the PKey table object
+*
+* SYNOPSIS
+*/
+int osm_pkey_tbl_init(
+ IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_destroy
+* NAME
+* osm_pkey_tbl_destroy
+*
+* DESCRIPTION
+* Destroys the PKey table object
+*
+* SYNOPSIS
+*/
+void osm_pkey_tbl_destroy(
+ IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_get_num_blocks
+* NAME
+* osm_pkey_get_num_blocks
+*
+* DESCRIPTION
+* Obtain the pointer to the IB PKey table block stored in the object
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_pkey_tbl_get_num_blocks(
+ IN const osm_pkey_tbl_t *p_pkey_tbl )
+{
+ return((uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks )));
+}
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* RETURN VALUES
+* The IB pkey table of that pkey table element
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_block_get
+* NAME
+* osm_pkey_tbl_block_get
+*
+* DESCRIPTION
+* Obtain the pointer to the IB PKey table block stored in the object
+*
+* SYNOPSIS
+*/
+static inline ib_pkey_table_t *osm_pkey_tbl_block_get(
+ const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block)
+{
+ CL_ASSERT(block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks));
+ return(cl_ptr_vector_get(&p_pkey_tbl->blocks, block));
+};
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* block
+* [in] The lock number to get
+*
+* RETURN VALUES
+* The IB pkey table of that pkey table element
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_set
+* NAME
+* osm_pkey_tbl_set
+*
+* DESCRIPTION
+* Set the PKey table block provided in the PKey object.
+*
+* SYNOPSIS
+*/
+int osm_pkey_tbl_set(
+ IN osm_pkey_tbl_t *p_pkey_tbl,
+ IN uint16_t block,
+ IN ib_pkey_table_t *p_tbl);
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* block
+* [in] The block number to set
+*
+* p_tbl
+* [in] The IB PKey block to copy to the object
+*
+* RETURN VALUES
+* IB_SUCCESS or IB_ERROR
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_share_pkey
+* NAME
+* osm_physp_share_pkey
+*
+* DESCRIPTION
+* Checks if the given physical ports share a pkey.
+* The meaning P_Key matching:
+* 10.9.3 :
+* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
+* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+* in the packet's destination endnode.
+*
+* If:
+* * neither M_P_Key nor E_P_Key are the invalid P_Key
+* * and the low-order 15 bits of the M_P_Key match the low order 15
+* bits of the E_P_Key
+* * and the high order bit(membership type) of both the M_P_Key and
+* E_P_Key are not both 0 (i.e., both are not Limited members of
+* the partition)
+*
+* then the P_Keys are said to match.
+*
+* SYNOPSIS
+*/
+boolean_t osm_physp_share_pkey(
+ IN osm_log_t* p_log,
+ IN const struct _osm_physp* const p_physp_1,
+ IN const struct _osm_physp* const p_physp_2 );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_physp_1
+* [in] Pointer to an osm_physp_t object.
+*
+* p_physp_2
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the 2 physical ports are matching.
+* FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_port_share_pkey
+* NAME
+* osm_port_share_pkey
+*
+* DESCRIPTION
+* Checks if the given ports (on their default physical port) share a pkey.
+* The meaning P_Key matching:
+* 10.9.3 :
+* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
+* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+* in the packet's destination endnode.
+*
+* If:
+* * neither M_P_Key nor E_P_Key are the invalid P_Key
+* * and the low-order 15 bits of the M_P_Key match the low order 15
+* bits of the E_P_Key
+* * and the high order bit(membership type) of both the M_P_Key and
+* E_P_Key are not both 0 (i.e., both are not Limited members of
+* the partition)
+*
+* then the P_Keys are said to match.
+*
+* SYNOPSIS
+*/
+boolean_t osm_port_share_pkey(
+ IN osm_log_t* p_log,
+ IN const struct _osm_port* const p_port_1,
+ IN const struct _osm_port* const p_port_2 );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_port_1
+* [in] Pointer to an osm_port_t object.
+*
+* p_port_2
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the 2 ports are matching.
+* FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_lid_share_pkey
+* NAME
+* osm_lid_share_pkey
+*
+* DESCRIPTION
+* Checks if the given lids and port_numbers share a pkey.
+* The meaning P_Key matching:
+* 10.9.3 :
+* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
+* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+* in the packet's destination endnode.
+*
+* If:
+* * neither M_P_Key nor E_P_Key are the invalid P_Key
+* * and the low-order 15 bits of the M_P_Key match the low order 15
+* bits of the E_P_Key
+* * and the high order bit(membership type) of both the M_P_Key and
+* E_P_Key are not both 0 (i.e., both are not Limited members of
+* the partition)
+*
+* then the P_Keys are said to match.
+*
+* SYNOPSIS
+*/
+boolean_t osm_lid_share_pkey(
+ IN osm_log_t* p_log,
+ IN const struct _osm_subn* const p_subn,
+ IN const ib_net16_t lid1,
+ IN const uint8_t port_num1,
+ IN const ib_net16_t lid2,
+ IN const uint8_t port_num2 );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to the subnet object for accessing of the options.
+*
+* lid1
+* [in] lid number of first port.
+*
+* port_num1
+* [in] port number of first port.
+*
+* lid2
+* [in] lid number of second port.
+*
+* port_num2
+* [in] port number of second port.
+*
+* RETURN VALUES
+* Returns TRUE if the 2 physical ports that belong to these lids/port_numbers
+* are matching. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_has_pkey
+* NAME
+* osm_physp_has_pkey
+*
+* DESCRIPTION
+* Checks if the given lids and port_numbers share a pkey.
+* The meaning P_Key matching:
+* 10.9.3 :
+* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming
+* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+* in the packet's destination endnode.
+*
+* If:
+* * neither M_P_Key nor E_P_Key are the invalid P_Key
+* * and the low-order 15 bits of the M_P_Key match the low order 15
+* bits of the E_P_Key
+* * and the high order bit(membership type) of both the M_P_Key and
+* E_P_Key are not both 0 (i.e., both are not Limited members of
+* the partition)
+*
+* then the P_Keys are said to match.
+*
+* SYNOPSIS
+*/
+boolean_t osm_physp_has_pkey(
+ IN osm_log_t* p_log,
+ IN const ib_net16_t pkey,
+ IN const struct _osm_physp* const p_physp );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* pkey
+* [in] pkey number to look for.
+*
+* p_physp
+* [in] Pointer to osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the p_physp has the pkey given. False otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_get_tables
+* NAME
+* osm_pkey_get_tables
+*
+* DESCRIPTION
+* Sends a request for getting the pkey tables of the given physp.
+*
+* SYNOPSIS
+*/
+void osm_pkey_get_tables(
+ IN osm_log_t *p_log,
+ IN osm_req_t *p_req,
+ IN osm_subn_t* const p_subn,
+ IN struct _osm_node* const p_node,
+ IN struct _osm_physp* const p_physp );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to osm_log object.
+*
+* p_req
+* [in] Pointer to osm_req object.
+*
+* p_subn
+* [in] Pointer to osm_subn object.
+*
+* p_node
+* [in] Pointer to osm_node object.
+*
+* p_physp
+* [in] Pointer to osm_physp_t object.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pkey_conf_ctrl_t.
+ * This object represents a controller that performs a
+ * Set(P_KeyTable) for the specified port.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PKEY_CONFIG_CTRL_H_
+#define _OSM_PKEY_CONFIG_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Table Configuration Controller
+* NAME
+* P_Key Table Configuration Controller
+*
+* DESCRIPTION
+* The P_Key Table Configuration Controller object encapsulates the
+* information needed to Set(PortInfo) at the specified port.
+*
+* The P_Key Table Configuration Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_t
+* NAME
+* osm_pkey_conf_ctrl_t
+*
+* DESCRIPTION
+* P_Key Table Configuration Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_conf_ctrl
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_pkey_conf_ctrl_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller object
+*********/
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_construct
+* NAME
+* osm_pkey_conf_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_conf_ctrl_construct(
+ IN osm_pkey_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_conf_ctrl_init, osm_pkey_conf_ctrl_destroy,
+* and osm_pkey_conf_ctrl_is_inited.
+*
+* Calling osm_pkey_conf_ctrl_construct is a prerequisite to calling any other
+* method except osm_pkey_conf_ctrl_init.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_init,
+* osm_pkey_conf_ctrl_destroy, osm_pkey_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_destroy
+* NAME
+* osm_pkey_conf_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pkey_conf_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_conf_ctrl_destroy(
+ IN osm_pkey_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Table Configuration Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_conf_ctrl_construct or osm_pkey_conf_ctrl_init.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+* osm_pkey_conf_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_init
+* NAME
+* osm_pkey_conf_ctrl_init
+*
+* DESCRIPTION
+* The osm_pkey_conf_ctrl_init function initializes a
+* P_Key Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_conf_ctrl_init(
+ IN osm_pkey_conf_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_conf_ctrl_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Table Configuration Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Table Configuration Controller methods.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+* osm_pkey_conf_ctrl_destroy, osm_pkey_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_is_inited
+* NAME
+* osm_pkey_conf_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pkey_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pkey_conf_ctrl_is_inited(
+ IN const osm_pkey_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_conf_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pkey_conf_ctrl_construct or osm_pkey_conf_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+* osm_pkey_conf_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_process
+* NAME
+* osm_pkey_conf_ctrl_process
+*
+* DESCRIPTION
+* Initiate a P_KeyTable configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_conf_ctrl_process(
+ IN const osm_pkey_conf_ctrl_t* const p_ctrl,
+ IN const ib_guid_t guid );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_conf_ctrl_t object.
+*
+* guid
+* [in] GUID of port to configure.
+*
+* RETURN VALUES
+* CL_SUCCESS if configuration processing was successfully
+* initiated.
+*
+* NOTES
+* A success status here does not indicate that
+* the P_Key Table configuration completed successfully.
+*
+* SEE ALSO
+* P_Key Table Configuration Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_CONFIG_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+#ifndef _OSM_PKEY_RCV_H_
+#define _OSM_PKEY_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Receiver
+* NAME
+* P_Key Receiver
+*
+* DESCRIPTION
+* The P_Key Receiver object encapsulates the information
+* needed to set or get the vl arbitration attribute from a port.
+*
+* The P_Key Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+/****s* OpenSM: P_Key Receiver/osm_pkey_rcv_t
+* NAME
+* osm_pkey_rcv_t
+*
+* DESCRIPTION
+* P_Key Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_pkey_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_construct
+* NAME
+* osm_pkey_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_construct(
+ IN osm_pkey_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rcv_destroy
+*
+* Calling osm_pkey_rcv_construct is a prerequisite to calling any other
+* method except osm_pkey_rcv_init.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_init,
+* osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_destroy
+* NAME
+* osm_pkey_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_destroy(
+ IN osm_pkey_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rcv_construct or osm_pkey_rcv_init.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_construct,
+* osm_pkey_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_init
+* NAME
+* osm_pkey_rcv_init
+*
+* DESCRIPTION
+* The osm_pkey_rcv_init function initializes a
+* P_Key Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_init(
+ IN osm_pkey_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Receiver methods.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_construct,
+* osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_process
+* NAME
+* osm_pkey_rcv_process
+*
+* DESCRIPTION
+* Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_process(
+ IN const osm_pkey_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* P_Key Receiver, P_Key Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+#ifndef _OSM_PKEY_RCV_CTRL_H_
+#define _OSM_PKEY_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_pkey_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Table Receive Controller
+* NAME
+* P_Key Receive Controller
+*
+* DESCRIPTION
+* The P_Key Receive Controller object encapsulates
+* the information needed to get or set P_Key table of a port.
+*
+* The P_Key Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+/****s* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_t
+* NAME
+* osm_pkey_rcv_ctrl_t
+*
+* DESCRIPTION
+* P_Key Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv_ctrl
+{
+ osm_pkey_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pkey_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the P_Key Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* P_Key Receive Controller object
+* P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_construct
+* NAME
+* osm_pkey_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_construct(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rcv_ctrl_init, osm_pkey_rcv_ctrl_destroy,
+* and osm_pkey_rcv_ctrl_is_inited.
+*
+* Calling osm_pkey_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_init,
+* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_destroy
+* NAME
+* osm_pkey_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_destroy(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_init
+* NAME
+* osm_pkey_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pkey_rcv_ctrl_init function initializes a
+* P_Key Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_ctrl_init(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pkey_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Receive Controller methods.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_is_inited
+* NAME
+* osm_pkey_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pkey_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pkey_rcv_ctrl_is_inited(
+ IN const osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of port related objects.
+ * These objects comprise an IBA port.
+ * These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#ifndef _OSM_PORT_H_
+#define _OSM_PORT_H_
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_memory.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_pkey.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ Forward references.
+*/
+struct _osm_port;
+struct _osm_node;
+
+/****h* OpenSM/Physical Port
+* NAME
+* Physical Port
+*
+* DESCRIPTION
+* The Physical Port object encapsulates the information needed by the
+* OpenSM to manage physical ports. The OpenSM allocates one Physical Port
+* per physical port in the IBA subnet.
+*
+* In a switch, one multiple Physical Port objects share the same port GUID.
+* In an end-point, Physical Ports do not share GUID values.
+*
+* The Physical Port is not thread safe, thus callers must provide
+* serialization.
+*
+* These objects should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Physical Port/osm_physp_t
+* NAME
+* osm_physp_t
+*
+* DESCRIPTION
+* This object represents a physical port on a switch, router or end-point.
+*
+* The osm_physp_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_physp
+{
+ ib_port_info_t port_info;
+ ib_net64_t port_guid;
+ uint8_t port_num;
+ struct _osm_node *p_node;
+ struct _osm_physp *p_remote_physp;
+ boolean_t healthy;
+ osm_dr_path_t dr_path;
+ osm_pkey_tbl_t pkeys;
+ ib_vl_arb_table_t vl_arb[4];
+ cl_ptr_vector_t slvl_by_port;
+ boolean_t got_set_resp;
+} osm_physp_t;
+/*
+* FIELDS
+* port_info
+* The IBA defined PortInfo data for this port.
+*
+* port_guid
+* Port GUID value of this port. For switches,
+* all ports share the same GUID value.
+*
+* port_num
+* The port number of this port. The PortInfo also
+* contains a port_number, but that number is not
+* the port number of this port, but rather the number
+* of the port that received the SMP during discovery.
+* Therefore, we must keep a separate record for this
+* port's port number.
+*
+* p_node
+* Pointer to the parent Node object of this Physical Port.
+*
+* p_remote_physp
+* Pointer to the Physical Port on the other side of the wire.
+* If this pointer is NULL no link exists at this port.
+*
+* healthy
+* Tracks the health of the port. Normally should be TRUE but
+* might change as a result of incoming traps indicating the port
+* healthy is questionable.
+*
+* dr_path
+* The directed route path to this port.
+*
+* pkeys
+* osm_pkey_tbl_t object holding the port PKeys.
+*
+* vl_arb[]
+* Each Physical Port has 4 sections of VL Arbitration table.
+*
+* slvl_by_port
+* A vector of pointers to the sl2vl tables (ordered by input port).
+* On switches have an entry for each other input port (inc SMA=0).
+* On CAs only one per port.
+*
+* got_set_resp
+* Marks whether or not we got a PortInfoSetResp from this port or not.
+* This is used for minimizing the number of PortInfoSet requests sent.
+* If we already got a set response from this port, then we will send
+* a PortInfoSet only if the values we are updating are different than
+* the ones on the port. If the haven't gotten a set response - then we
+* want to send the request anyways - since every we need at least one
+* PortInfoSet request for every port (by a new SM).
+*
+* SEE ALSO
+* Port
+*********/
+/****f* OpenSM: Physical Port/osm_physp_construct
+* NAME
+* osm_physp_construct
+*
+* DESCRIPTION
+* Constructs a Physical Port.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_construct(
+ IN osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object to initialize.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+/****f* OpenSM: Physical Port/osm_physp_init
+* NAME
+* osm_physp_init
+*
+* DESCRIPTION
+* Initializes a Physical Port for use.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_init(
+ IN osm_physp_t* const p_physp,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const struct _osm_node* const p_node,
+ IN const osm_bind_handle_t h_bind,
+ IN const uint8_t hop_count,
+ IN const uint8_t* const p_initial_path );
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object to initialize.
+*
+* port_guid
+* [in] GUID value of this port. Switch ports all share
+* the same value.
+* Caller should use 0 if the guid is unknown.
+*
+* port_num
+* [in] The port number of this port.
+*
+* p_node
+* [in] Pointer to the parent Node object of this Physical Port.
+*
+* h_bind
+* [in] Bind handle on which this port is accessed.
+* Caller should use OSM_INVALID_BIND_HANDLE if the bind
+* handle to this port is unknown.
+*
+* hop_count
+* [in] Directed route hop count to reach this port.
+* Caller should use 0 if the hop count is unknown.
+*
+* p_initial_path
+* [in] Pointer to the directed route path to reach this node.
+* Caller should use NULL if the path is unknown.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Port/void osm_physp_destroy
+* NAME
+* osm_physp_destroy
+*
+* DESCRIPTION
+* This function destroys a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_destroy(
+ IN osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a PhysPort object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified PhysPort object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_physp_construct or
+* osm_physp_init.
+*
+* SEE ALSO
+* Port, osm_port_init, port_estroy, osm_port_is_inited
+*********/
+/****f* OpenSM: Physical Port/osm_physp_is_valid
+* NAME
+* osm_physp_is_valid
+*
+* DESCRIPTION
+* Returns TRUE if the Physical Port has been successfully initialized.
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_is_valid(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ return( p_physp->port_guid != 0 );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the Physical Port has been successfully initialized.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_is_healthy
+* NAME
+* osm_physp_is_healthy
+*
+* DESCRIPTION
+* Returns TRUE if the Physical Port has been maked as healthy
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_is_healthy(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ return( p_physp->healthy );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the Physical Port has been maked as healthy
+* FALSE otherwise.
+* All physical ports are initialized as "healthy" but may be marked
+* otherwise if a received trap claims otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_link_is_healthy
+* NAME
+* osm_link_is_healthy
+*
+* DESCRIPTION
+* Returns TRUE if the link given by the physical port is health,
+* and FALSE otherwise. Link is healthy if both its physical ports are
+* healthy
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_link_is_healthy(
+ IN const osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* TRUE if both physical ports on the link are healthy, and FALSE otherwise.
+* All physical ports are initialized as "healthy" but may be marked
+* otherwise if a received trap claiming otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_health
+* NAME
+* osm_physp_set_health
+*
+* DESCRIPTION
+* Sets the port health flag. TRUE means the port is healthy and
+* should be used for packet routing. FALSE means it should be avoided.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_health(
+ IN osm_physp_t* const p_physp,
+ IN boolean_t is_healthy )
+{
+ CL_ASSERT( p_physp );
+ p_physp->healthy = is_healthy;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* is_healthy
+* [in] The health value to be assigned to the port.
+* TRUE if the Physical Port should been maked as healthy
+* FALSE otherwise.
+*
+* RETURN VALUES
+* NONE
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_port_info
+* NAME
+* osm_physp_set_port_info
+*
+* DESCRIPTION
+* Copies the PortInfo attribute into the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_port_info(
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ CL_ASSERT( p_pi );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ p_physp->port_info = *p_pi;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_pi
+* [in] Pointer to the IBA defined PortInfo at this port number.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_pkey_tbl
+* NAME
+* osm_physp_set_pkey_tbl
+*
+* DESCRIPTION
+* Copies the P_Key table into the Physical Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_set_pkey_tbl( IN osm_log_t* p_log,
+ IN const osm_subn_t* p_subn,
+ IN osm_physp_t* const p_physp,
+ IN ib_pkey_table_t *p_pkey_tbl,
+ IN uint16_t block_num);
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to the subnet data structure.
+*
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_pkey_tbl
+* [in] Pointer to the IBA defined P_Key table for this port number.
+*
+* block_num
+* [in] The part of the P_Key table as defined in the IBA
+* (valid values 0-2047, and is further limited by the partitionCap).
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_pkey_tbl
+* NAME
+* osm_physp_get_pkey_tbl
+*
+* DESCRIPTION
+* Returns a pointer to the P_Key table object of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline const osm_pkey_tbl_t *
+osm_physp_get_pkey_tbl( IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ /*
+ (14.2.5.7) - the block number valid values are 0-2047, and are further
+ limited by the size of the P_Key table specified by the PartitionCap on the node.
+ */
+ return( &p_physp->pkeys );
+};
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* The pointer to the P_Key table object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_slvl_tbl
+* NAME
+* osm_physp_set_slvl_tbl
+*
+* DESCRIPTION
+* Copies the SLtoVL attribute into the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_slvl_tbl( IN osm_physp_t* const p_physp,
+ IN ib_slvl_table_t *p_slvl_tbl,
+ IN uint8_t in_port_num) {
+ ib_slvl_table_t *p_tbl;
+ CL_ASSERT( p_slvl_tbl );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num);
+ *p_tbl = *p_slvl_tbl;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_slvl_tbl
+* [in] Pointer to the IBA defined SLtoVL map table for this port number.
+*
+* in_port_num
+* [in] Input Port Number for this SLtoVL.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_slvl_tbl
+* NAME
+* osm_physp_get_slvl_tbl
+*
+* DESCRIPTION
+* Returns a pointer to the SLtoVL attribute of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline ib_slvl_table_t *
+osm_physp_get_slvl_tbl( IN const osm_physp_t* const p_physp,
+ IN uint8_t in_port_num) {
+ ib_slvl_table_t *p_tbl;
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num);
+ return(p_tbl);
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* in_port_num
+* [in] Input Port Number for this SLtoVL.
+*
+* RETURN VALUES
+* The pointer to the slvl table
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_vla_tbl
+* NAME
+* osm_physp_set_vla_tbl
+*
+* DESCRIPTION
+* Copies the VL Arbitration attribute into the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_vla_tbl( IN osm_physp_t* const p_physp,
+ IN ib_vl_arb_table_t *p_vla_tbl,
+ IN uint8_t block_num) {
+ CL_ASSERT( p_vla_tbl );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( (1 <= block_num) && (block_num <= 4));
+ p_physp->vl_arb[block_num - 1] = *p_vla_tbl;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_vla_tbl
+* [in] Pointer to the IBA defined VL Arbitration table for this port number.
+*
+* block_num
+* [in] The part of the VL arbitration as defined in the IBA (valid values 1-4)
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_vla_tbl
+* NAME
+* osm_physp_get_vla_tbl
+*
+* DESCRIPTION
+* Returns a pointer to the VL Arbitration table of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline ib_vl_arb_table_t *
+osm_physp_get_vla_tbl( IN osm_physp_t* const p_physp,
+ IN uint8_t block_num) {
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( (1 <= block_num) && (block_num <= 4));
+ return(& (p_physp->vl_arb[block_num - 1]));
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* block_num
+* [in] The part of the VL arbitration as defined in the IBA (valid values 1-4)
+*
+* RETURN VALUES
+* The pointer to the vl arbitration table
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_remote
+* NAME
+* osm_physp_get_remote
+*
+* DESCRIPTION
+* Returns a pointer to the Physical Port on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_physp_get_remote(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( p_physp->p_remote_physp );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the Physical Port on the other side of
+* the wire. A return value of NULL means there is no link at this port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+/****f* OpenSM: Physical Port/osm_physp_get_port_guid
+* NAME
+* osm_physp_get_port_guid
+*
+* DESCRIPTION
+* Returns the port guid of this physical port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_physp_get_port_guid(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( p_physp->port_guid );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the port guid of this physical port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_subnet_prefix
+* NAME
+* osm_physp_get_subnet_prefix
+*
+* DESCRIPTION
+* Returns the subnet prefix for this physical port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_physp_get_subnet_prefix(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( p_physp->port_info.subnet_prefix );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the subnet prefix for this physical port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_link_exists
+* NAME
+* osm_physp_link_exists
+*
+* DESCRIPTION
+* Returns TRUE if the Physical Port has a link to the specified port.
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_link_exists(
+ IN const osm_physp_t* const p_physp,
+ IN const osm_physp_t* const p_remote_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( p_remote_physp );
+ CL_ASSERT( osm_physp_is_valid( p_remote_physp ) );
+ return( (p_physp->p_remote_physp == p_remote_physp ) &&
+ (p_remote_physp->p_remote_physp == p_physp ) );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_remote_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the Physical Port has a link to another port.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+
+/****f* OpenSM: Physical Port/osm_physp_link
+* NAME
+* osm_physp_link
+*
+* DESCRIPTION
+* Sets the pointers to the Physical Ports on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_link(
+ IN osm_physp_t* const p_physp,
+ IN osm_physp_t* const p_remote_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( p_remote_physp );
+ p_physp->p_remote_physp = p_remote_physp;
+ p_remote_physp->p_remote_physp = p_physp;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object to link.
+*
+* p_remote_physp
+* [in] Pointer to the adjacent osm_physp_t object to link.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_unlink
+* NAME
+* osm_physp_unlink
+*
+* DESCRIPTION
+* Clears the pointers to the Physical Port on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_unlink(
+ IN osm_physp_t* const p_physp,
+ IN osm_physp_t* const p_remote_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( p_remote_physp );
+ CL_ASSERT( osm_physp_link_exists( p_physp, p_remote_physp ) );
+ p_physp->p_remote_physp = NULL;
+ p_remote_physp->p_remote_physp = NULL;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object to link.
+*
+* p_remote_physp
+* [in] Pointer to the adjacent osm_physp_t object to link.
+*
+* RETURN VALUES
+* Returns a pointer to the Physical Port on the other side of
+* the wire. A return value of NULL means there is no link at this port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+
+/****f* OpenSM: Physical Port/osm_physp_has_any_link
+* NAME
+* osm_physp_has_any_link
+*
+* DESCRIPTION
+* Returns TRUE if the Physical Port has a link to another port.
+* FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_has_any_link(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ if( osm_physp_is_valid( p_physp ) )
+ return( p_physp->p_remote_physp != NULL );
+ else
+ return( FALSE );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the Physical Port has a link to another port.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_num
+* NAME
+* osm_physp_get_port_num
+*
+* DESCRIPTION
+* Returns the local port number of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_port_num(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( p_physp->port_num );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the local port number of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Physical Port/osm_physp_get_port_info_ptr
+* NAME
+* osm_physp_get_port_info_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the PortInfo attribute for this port.
+*
+* SYNOPSIS
+*/
+static inline ib_port_info_t*
+osm_physp_get_port_info_ptr(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( (ib_port_info_t*)&p_physp->port_info );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the PortInfo attribute for this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Physical Port/osm_physp_get_node_ptr
+* NAME
+* osm_physp_get_node_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the parent Node object for this port.
+*
+* SYNOPSIS
+*/
+static inline struct _osm_node*
+osm_physp_get_node_ptr(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( (struct _osm_node*)p_physp->p_node );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the parent Node object for this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_state
+* NAME
+* osm_physp_get_port_state
+*
+* DESCRIPTION
+* Returns the port state of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_port_state(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( ib_port_info_get_port_state( &p_physp->port_info ));
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the local port number of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Physical Port/osm_physp_get_base_lid
+* NAME
+* osm_physp_get_base_lid
+*
+* DESCRIPTION
+* Returns the base lid of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_physp_get_base_lid(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( p_physp->port_info.base_lid );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the base lid of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_lmc
+* NAME
+* osm_physp_get_lmc
+*
+* DESCRIPTION
+* Returns the LMC value of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_lmc(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( ib_port_info_get_lmc( &p_physp->port_info ) );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns the LMC value of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_dr_path_ptr
+* NAME
+* osm_physp_get_dr_path_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the directed route path for this port.
+*
+* SYNOPSIS
+*/
+static inline osm_dr_path_t*
+osm_physp_get_dr_path_ptr(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( (osm_dr_path_t*)&p_physp->dr_path );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to a Physical Port object.
+*
+* RETURN VALUES
+* Returns a pointer to the directed route path for this port.
+*
+* NOTES
+*
+* SEE ALSO
+* Physical Port object
+*********/
+
+/****h* OpenSM/Port
+* NAME
+* Port
+*
+* DESCRIPTION
+* The Port object encapsulates the information needed by the
+* OpenSM to manage ports. The OpenSM allocates one Port object
+* per port in the IBA subnet.
+*
+* Each Port object is associated with a single port GUID. A Port object
+* contains 1 or more Physical Port objects. An end point node has
+* one Physical Port per Port. A switch node has more than
+* one Physical Port per Port.
+*
+* The Port object is not thread safe, thus callers must provide
+* serialization.
+*
+* These objects should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****d* OpenSM: Port/osm_port_lid_category_t
+* NAME
+* osm_port_lid_category_t
+*
+* DESCRIPTION
+* Enumerated values for LID dispostion.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_port_lid_category
+{
+ OSM_PORT_LID_ASSIGNED = 0,
+ OSM_PORT_LID_UNASSIGNED,
+ OSM_PORT_LID_CONFLICT,
+ OSM_PORT_LID_FOREIGN,
+
+} osm_port_lid_category_t;
+/*
+* FIELDS
+* OSM_PORT_LID_ASSIGNED
+* Indicates the Port has a known LID value.
+*
+* OSM_PORT_LID_UNASSIGNED
+* Indicates the Port does not have a LID value.
+*
+* OSM_PORT_LID_CONFLICT
+* Indicates the Port's LID conflicts with an assigned LID.
+*
+* OSM_PORT_LID_FOREIGN
+* Indicates the Port has a LID value not currently known in
+* in the OpenSM LID database.
+*
+* SEE ALSO
+* Port
+*********/
+
+/****s* OpenSM: Port/osm_port_t
+* NAME
+* osm_port_t
+*
+* DESCRIPTION
+* This object represents a logical port on a switch, router or end-point.
+*
+* The osm_port_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_port
+{
+ cl_map_item_t map_item;
+ struct _osm_node *p_node;
+ ib_net64_t guid;
+ uint32_t discovery_count;
+ uint8_t default_port_num;
+ uint8_t physp_tbl_size;
+ cl_qlist_t mcm_list;
+ osm_physp_t *tbl[1];
+
+} osm_port_t;
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* p_node
+* Points to the Node object that owns this port.
+*
+* guid
+* Manufacturer assigned GUID for this port.
+*
+* discovery_count
+* The number of times this port has been discovered
+* during the current fabric sweep. This number is reset
+* to zero at the start of a sweep.
+*
+* default_port_num
+* Index of the physical port used when physical characteristics
+* contained in the Physical Port are needed.
+*
+* physp_tbl_size
+* Number of physical ports associated with this logical port.
+*
+* mcm_list
+* Multicast member list
+*
+* tbl
+* Array of pointers to Physical Port objects contained by this node.
+* MUST BE LAST ELEMENT SINCE IT CAN GROW !!!
+*
+* SEE ALSO
+* Port, Physical Port, Physical Port Table
+*********/
+
+/****f* OpenSM: Port/osm_port_construct
+* NAME
+* osm_port_construct
+*
+* DESCRIPTION
+* This function constructs a Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_construct(
+ IN osm_port_t* const p_port )
+{
+ cl_memclr( p_port, sizeof(*p_port) );
+ cl_qlist_init( &p_port->mcm_list );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_port_init, osm_port_destroy, and osm_port_is_inited.
+*
+* Calling osm_port_construct is a prerequisite to calling any other
+* method except osm_port_init.
+*
+* SEE ALSO
+* Port, osm_port_init, osm_port_destroy, osm_port_is_inited
+*********/
+
+/****f* OpenSM: Port/osm_port_destroy
+* NAME
+* osm_port_destroy
+*
+* DESCRIPTION
+* This function destroys a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_destroy(
+ IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Port object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_port_construct or
+* osm_port_init.
+*
+* SEE ALSO
+* Port, osm_port_init, osm_port_destroy, osm_port_is_inited
+*********/
+/****f* OpenSM: Port/osm_port_destroy
+* NAME
+* osm_port_destroy
+*
+* DESCRIPTION
+* This function destroys and deallocates a Port object.
+*
+* SYNOPSIS
+*/
+inline static void
+osm_port_delete(
+ IN OUT osm_port_t** const pp_port )
+{
+ osm_port_destroy( *pp_port );
+ cl_free( *pp_port );
+ *pp_port = NULL;
+}
+/*
+* PARAMETERS
+* pp_port
+* [in][out] Pointer to a pointer to a Port oject to delete.
+* On return, this pointer is NULL.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Port object.
+*
+* SEE ALSO
+* Port, osm_port_init, osm_port_destroy
+*********/
+/****f* OpenSM: Port/osm_port_init
+* NAME
+* osm_port_init
+*
+* DESCRIPTION
+* This function initializes a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_init(
+ IN osm_port_t* const p_port,
+ IN const ib_node_info_t* p_ni,
+ IN const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject to initialize.
+*
+* p_ni
+* [in] Pointer to the NodeInfo attribute relavent for this port.
+*
+* p_parent_node
+* [in] Pointer to the initialized parent osm_node_t object
+* that owns this port.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+* Allows calling other port methods.
+*
+* SEE ALSO
+* Port
+*********/
+/****f* OpenSM: Port/osm_port_new
+* NAME
+* osm_port_new
+*
+* DESCRIPTION
+* This function allocates and initializes a Port object.
+*
+* SYNOPSIS
+*/
+osm_port_t*
+osm_port_new(
+ IN const ib_node_info_t* p_ni,
+ IN const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to the NodeInfo attribute relavent for this port.
+*
+* p_parent_node
+* [in] Pointer to the initialized parent osm_node_t object
+* that owns this port.
+*
+* RETURN VALUE
+* Pointer to the initialize Port object.
+*
+* NOTES
+* Allows calling other port methods.
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_base_lid
+* NAME
+* osm_port_get_base_lid
+*
+* DESCRIPTION
+* Gets the base LID of a port.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_port_get_base_lid(
+ IN const osm_port_t* const p_port )
+{
+ const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( osm_physp_get_base_lid( p_physp ));
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* RETURN VALUE
+* Base LID of the port.
+* If the return value is 0, then this port has no assigned LID.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+/****f* OpenSM: Port/osm_port_get_lmc
+* NAME
+* osm_port_get_lmc
+*
+* DESCRIPTION
+* Gets the LMC value of a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_port_get_lmc(
+ IN const osm_port_t* const p_port )
+{
+ const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( osm_physp_get_lmc( p_physp ));
+}
+
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* RETURN VALUE
+* Gets the LMC value of a port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_guid
+* NAME
+* osm_port_get_guid
+*
+* DESCRIPTION
+* Gets the GUID of a port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_port_get_guid(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->guid );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* RETURN VALUE
+* Manufacturer assigned GUID of the port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_num_physp
+* NAME
+* osm_port_get_num_physp
+*
+* DESCRIPTION
+* Returns the number of Physical Port objects associated with this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_port_get_num_physp(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->physp_tbl_size );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* RETURN VALUE
+* Returns the number of Physical Port objects associated with this port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_phys_ptr
+* NAME
+* osm_port_get_phys_ptr
+*
+* DESCRIPTION
+* Gets the pointer to the specified Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_port_get_phys_ptr(
+ IN const osm_port_t* const p_port,
+ IN const uint8_t port_num )
+{
+ CL_ASSERT( port_num < p_port->physp_tbl_size );
+ return( p_port->tbl[port_num] );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* port_num
+* [in] Number of physical port for which to return the
+* osm_physp_t object. If this port is on an HCA, then
+* this value is ignored.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_phys_ptr
+* NAME
+* osm_port_get_phys_ptr
+*
+* DESCRIPTION
+* Gets the pointer to the default Physical Port object.
+* This call should only be used for non-switch ports in which there
+* is a one-for-one mapping of port to physp.
+*
+* SYNOPSIS
+*/
+static inline
+osm_physp_t*
+osm_port_get_default_phys_ptr(
+ IN const osm_port_t* const p_port )
+{
+ CL_ASSERT( p_port->tbl[p_port->default_port_num] );
+ CL_ASSERT( osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) );
+ return( p_port->tbl[p_port->default_port_num] );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_parent_node
+* NAME
+* osm_port_get_parent_node
+*
+* DESCRIPTION
+* Gets the pointer to the specified Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline struct _osm_node*
+osm_port_get_parent_node(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->p_node );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* port_num
+* [in] Number of physical port for which to return the
+* osm_physp_t object.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_lid_range_ho
+* NAME
+* osm_port_get_lid_range_ho
+*
+* DESCRIPTION
+* Returns the HOST ORDER lid min and max values for this port,
+* based on the lmc value.
+*
+* SYNOPSIS
+*/
+void
+osm_port_get_lid_range_ho(
+ IN const osm_port_t* const p_port,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const p_max_lid );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* p_min_lid
+* [out] Pointer to the minimum LID value occupied by this port.
+*
+* p_max_lid
+* [out] Pointer to the maximum LID value occupied by this port.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_add_new_physp
+* NAME
+* osm_port_add_new_physp
+*
+* DESCRIPTION
+* Adds a new physical port to the logical collection owned by the Port.
+* Physical Ports added here must share the same GUID as the Port.
+*
+* SYNOPSIS
+*/
+void
+osm_port_add_new_physp(
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port oject.
+*
+* port_num
+* [in] Port number to add.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_reset
+* NAME
+* osm_port_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this Port to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_reset(
+ IN osm_port_t* const p_port )
+{
+ p_port->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_get
+* NAME
+* osm_port_discovery_count_get
+*
+* DESCRIPTION
+* Returns the number of times this port has been discovered
+* since the last time the discovery count was reset.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_discovery_count_get(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->discovery_count );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* Returns the number of times this port has been discovered
+* since the last time the discovery count was reset.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_inc
+* NAME
+* osm_port_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this Port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_inc(
+ IN osm_port_t* const p_port )
+{
+ p_port->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_add_mgrp
+* NAME
+* osm_port_add_mgrp
+*
+* DESCRIPTION
+* Logically connects a port to a multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_port_add_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* mlid
+* [in] MLID of the multicast group.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_mgrp
+* NAME
+* osm_port_remove_mgrp
+*
+* DESCRIPTION
+* Logically disconnects a port from a multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* mlid
+* [in] MLID of the multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_all_mgrp
+* NAME
+* osm_port_remove_all_mgrp
+*
+* DESCRIPTION
+* Logically disconnects a port from all its multicast groups.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_all_mgrp(
+ IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_calc_link_mtu
+* NAME
+* osm_physp_calc_link_mtu
+*
+* DESCRIPTION
+* Calculate the Port MTU based on current and remote
+* physical ports MTU CAP values.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_physp_calc_link_mtu(
+ IN osm_log_t* p_log,
+ IN const osm_physp_t* p_physp );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* The MTU of the link to be used.
+*
+* NOTES
+*
+* SEE ALSO
+* PhysPort object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_calc_link_op_vls
+* NAME
+* osm_physp_calc_link_op_vls
+*
+* DESCRIPTION
+* Calculate the Port OP_VLS based on current and remote
+* physical ports VL CAP values. Allowing user option for a max limit.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_physp_calc_link_op_vls(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t * p_subn,
+ IN const osm_physp_t* p_physp );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to the subnet object for accessing of the options.
+*
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* The OP_VLS of the link to be used.
+*
+* NOTES
+*
+* SEE ALSO
+* PhysPort object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_replace_dr_path_with_alternate_dr_path
+* NAME
+* osm_physp_replace_dr_path_with_alternate_dr_path
+*
+* DESCRIPTION
+* Replace the direct route path for the given phys port with an
+* alternate path going through forien set of phys port.
+*
+* SYNOPSIS
+*/void
+osm_physp_replace_dr_path_with_alternate_dr_path(
+ IN osm_log_t *p_log,
+ IN osm_subn_t const *p_subn,
+ IN osm_physp_t const *p_physp,
+ IN osm_bind_handle_t *h_bind );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to the subnet object for accessing of the options.
+*
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* h_bind
+* [in] Pointer to osm_bind_handle_t object.
+*
+* RETURN VALUES
+* NONE
+*
+* NOTES
+*
+* SEE ALSO
+* PhysPort object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PORT_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PI_RCV_H_
+#define _OSM_PI_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Info Receiver
+* NAME
+* Port Info Receiver
+*
+* DESCRIPTION
+* The Port Info Receiver object encapsulates the information
+* needed to receive the PortInfo attribute from a node.
+*
+* The Port Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Port Info Receiver/osm_pi_rcv_t
+* NAME
+* osm_pi_rcv_t
+*
+* DESCRIPTION
+* Port Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_pi_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_construct
+* NAME
+* osm_pi_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Port Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_construct(
+ IN osm_pi_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Port Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pi_rcv_destroy
+*
+* Calling osm_pi_rcv_construct is a prerequisite to calling any other
+* method except osm_pi_rcv_init.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_init,
+* osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_destroy
+* NAME
+* osm_pi_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pi_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_destroy(
+ IN osm_pi_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Port Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pi_rcv_construct or osm_pi_rcv_init.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_construct,
+* osm_pi_rcv_init
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_init
+* NAME
+* osm_pi_rcv_init
+*
+* DESCRIPTION
+* The osm_pi_rcv_init function initializes a
+* Port Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_init(
+ IN osm_pi_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the state manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Port Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Port Info Receiver methods.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_construct,
+* osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_process
+* NAME
+* osm_pi_rcv_process
+*
+* DESCRIPTION
+* Process the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_process(
+ IN const osm_pi_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's PortInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfo processing was successful.
+*
+* NOTES
+* This function processes a PortInfo attribute.
+*
+* SEE ALSO
+* Port Info Receiver, Port Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PI_RCV_CTRL_H_
+#define _OSM_PI_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port_info_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Info Receive Controller
+* NAME
+* Port Info Receive Controller
+*
+* DESCRIPTION
+* The Port Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Port Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_t
+* NAME
+* osm_pi_rcv_ctrl_t
+*
+* DESCRIPTION
+* Port Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv_ctrl
+{
+ osm_pi_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pi_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Port Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Port Info Receive Controller object
+* Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_construct
+* NAME
+* osm_pi_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_construct(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Port Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pi_rcv_ctrl_init, osm_pi_rcv_ctrl_destroy,
+* and osm_pi_rcv_ctrl_is_inited.
+*
+* Calling osm_pi_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_init,
+* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_destroy
+* NAME
+* osm_pi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pi_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_destroy(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Port Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_init
+* NAME
+* osm_pi_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pi_rcv_ctrl_init function initializes a
+* Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_ctrl_init(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl,
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pi_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Port Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Port Info Receive Controller methods.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_is_inited
+* NAME
+* osm_pi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pi_rcv_ctrl_is_inited(
+ IN const osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_switch_t.
+ * This object represents an IBA switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#ifndef _OSM_PORT_PROFILE_H_
+#define _OSM_PORT_PROFILE_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Profile
+* NAME
+* Port Profile
+*
+* DESCRIPTION
+* The Port Profile object contains profiling information for
+* each Physical Port on a switch. The profile information
+* may be used to optimize path selection.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Switch/osm_port_profile_t
+* NAME
+* osm_port_profile_t
+*
+* DESCRIPTION
+* The Port Profile object contains profiling information for
+* each Physical Port on the switch. The profile information
+* may be used to optimize path selection.
+*
+* This object should be treated as opaque and should be
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_port_profile
+{
+ uint32_t num_paths;
+
+} osm_port_profile_t;
+/*
+* FIELDS
+* num_paths
+* The number of paths using this port.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_pro_construct
+* NAME
+* osm_port_pro_construct
+*
+* DESCRIPTION
+*
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_construct(
+ IN osm_port_profile_t* const p_pro )
+{
+ CL_ASSERT( p_pro );
+ cl_memclr( p_pro, sizeof(*p_pro) );
+}
+/*
+* PARAMETERS
+* p_pro
+* [in] Pointer to the Port Profile object to construct.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_pro_path_count_inc
+* NAME
+* osm_port_pro_path_count_inc
+*
+* DESCRIPTION
+* Increments the count of the number of paths going through this port.
+*
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_path_count_inc(
+ IN osm_port_profile_t* const p_pro )
+{
+ CL_ASSERT( p_pro );
+ p_pro->num_paths++;
+}
+/*
+* PARAMETERS
+* p_pro
+* [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_pro_path_count_get
+* NAME
+* osm_port_pro_path_count_get
+*
+* DESCRIPTION
+* Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_pro_path_count_get(
+ IN const osm_port_profile_t* const p_pro )
+{
+ return( p_pro->num_paths );
+}
+/*
+* PARAMETERS
+* p_pro
+* [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Port Profile Opt/osm_port_pro_is_ignored_port
+* NAME
+* osm_port_pro_is_ignored_port
+*
+* DESCRIPTION
+* Check to see if this port is to be ignored in path counting.
+* This is done by examining the optional list of port_pro_ignore_guids.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_port_pro_is_ignored_port(
+ IN const osm_subn_t *p_subn,
+ IN uint64_t port_guid,
+ IN uint8_t port_num) {
+ const cl_map_t *p_map = &(p_subn->opt.port_pro_ignore_guids);
+ const void *p_obj = cl_map_get(p_map, port_guid);
+ size_t res;
+ // HACK: we currently support ignoring ports 0 - 31
+ if (p_obj != NULL) {
+ res = (size_t)p_obj & (size_t)(1 << port_num);
+ return (res != 0);
+ }
+ return FALSE;
+}
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the OSM Subnet object.
+*
+* port_guid
+* [in] The port guid
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile Opt/osm_port_pro_set_ignored_port
+* NAME
+* osm_port_pro_set_ignored_port
+*
+* DESCRIPTION
+* Set the ignored property of the port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_set_ignored_port(
+ IN osm_subn_t *p_subn,
+ IN uint64_t port_guid,
+ IN uint8_t port_num) {
+ cl_map_t *p_map = &(p_subn->opt.port_pro_ignore_guids);
+ const void *p_obj = cl_map_get(p_map, port_guid);
+ size_t value = 0;
+ // HACK: we currently support ignoring ports 0 - 31
+ CL_ASSERT(port_num < 32);
+
+ if (p_obj != NULL) {
+ value = (size_t)p_obj;
+ }
+
+ value = value | (1 << port_num);
+ cl_map_insert(&(p_subn->opt.port_pro_ignore_guids),
+ port_guid,
+ (void *)value);
+}
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the OSM Subnet object.
+*
+* port_guid
+* [in] The port guid
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PORT_PROFILE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_switch_t.
+ * This object represents an IBA switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_RAND_FWD_TBL_H_
+#define _OSM_RAND_FWD_TBL_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Random Forwarding Table
+* NAME
+* Random Forwarding Table
+*
+* DESCRIPTION
+* The Random Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage random forwarding tables. The OpenSM
+* allocates one Random Forwarding Table object per switch in the
+* IBA subnet, if that switch uses a random forwarding table.
+*
+* The Random Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* ** RANDOM FORWARDING TABLES ARE NOT SUPPORTED IN THE CURRENT VERSION **
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_rand_fwd_tbl_t
+* NAME
+* osm_rand_fwd_tbl_t
+*
+* DESCRIPTION
+* Random Forwarding Table structure.
+*
+* THIS OBJECT IS PLACE HOLDER. SUPPORT FOR SWITCHES WITH
+* RANDOM FORWARDING TABLES HAS NOT BEEN IMPLEMENTED YET.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_rand_fwd_tbl
+{
+ /* PLACE HOLDER STRUCTURE ONLY!! */
+ uint32_t size;
+
+} osm_rand_fwd_tbl_t;
+/*
+* FIELDS
+* RANDOM FORWARDING TABLES ARE NOT SUPPORTED YET!!
+*
+* SEE ALSO
+* Forwarding Table object, Random Fowarding Table object.
+*********/
+/****f* OpenSM: Forwarding Table/osm_rand_tbl_delete
+* NAME
+* osm_rand_tbl_delete
+*
+* DESCRIPTION
+* This destroys and deallocates a Random Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_tbl_delete(
+ IN osm_rand_fwd_tbl_t** const pp_tbl )
+{
+ /*
+ TO DO - This is a place holder function only!
+ */
+ cl_free( *pp_tbl );
+ *pp_tbl = NULL;
+}
+/*
+* PARAMETERS
+* pp_tbl
+* [in] Pointer a Pointer to the Random Forwarding Table object.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set
+* NAME
+* osm_rand_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_fwd_tbl_set(
+ IN osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ /* Random forwarding tables not supported yet. */
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_ho );
+ UNUSED_PARAM( port );
+ CL_ASSERT( FALSE );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Random Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set_block
+* NAME
+* osm_rand_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Random Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_rand_fwd_tbl_set_block(
+ IN osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ /* Random forwarding tables not supported yet. */
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( p_block );
+ UNUSED_PARAM( block_num );
+ CL_ASSERT( FALSE );
+ return( IB_ERROR );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Random Forwarding Table object.
+*
+* p_block
+* [in] Pointer to the Forwarding Table block.
+*
+* block_num
+* [in] Block number of this block.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get
+* NAME
+* osm_rand_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_rand_fwd_tbl_get(
+ IN const osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho )
+{
+ CL_ASSERT( FALSE );
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_ho );
+
+ return( OSM_NO_PATH );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_lids_per_block
+* NAME
+* osm_rand_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_lids_per_block(
+ IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ return( 16 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_rand_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_top_ho );
+ CL_ASSERT( FALSE );
+ return( 0 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_size
+* NAME
+* osm_rand_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_size(
+ IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ CL_ASSERT( FALSE );
+ return( 0 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RAND_FWD_TBL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_t, osm_remote_sm_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REMOTE_SM_H_
+#define _OSM_REMOTE_SM_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Remote SM
+* NAME
+* Remote SM
+*
+* DESCRIPTION
+* The Remote SM object encapsulates the information tracked for
+* other SM ports on the subnet.
+*
+* The Remote SM object is thread safe.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Remote SM/osm_remote_sm_t
+* NAME
+* osm_remote_sm_t
+*
+* DESCRIPTION
+* Remote Subnet Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_remote_sm
+{
+ cl_map_item_t map_item;
+ const osm_port_t *p_port;
+ ib_sm_info_t smi;
+ boolean_t is_opensm;
+
+} osm_remote_sm_t;
+/*
+* FIELDS
+* map_item
+* Linkage for the cl_qmap container. MUST BE FIRST ELEMENT!!
+* p_port
+* Pointer to the port object for this SM.
+*
+* smi
+* The SMInfo attribute for this SM.
+*
+* is_opensm
+* TRUE if this SM is an OpenSM.
+* FALSE otherwise.
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: SM/osm_remote_sm_construct
+* NAME
+* osm_remote_sm_construct
+*
+* DESCRIPTION
+* This function constructs an Remote SM object.
+*
+* SYNOPSIS
+*/
+void
+osm_remote_sm_construct(
+ IN osm_remote_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an Remote SM object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_remote_sm_init, osm_remote_sm_destroy
+*
+* Calling osm_remote_sm_construct is a prerequisite to calling any other
+* method except osm_remote_sm_init.
+*
+* SEE ALSO
+* SM object, osm_remote_sm_init, osm_remote_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_remote_sm_destroy
+* NAME
+* osm_remote_sm_destroy
+*
+* DESCRIPTION
+* The osm_remote_sm_destroy function destroys an SM, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_remote_sm_destroy(
+ IN osm_remote_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an Remote SM object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Remote SM object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_remote_sm_construct or osm_remote_sm_init.
+*
+* SEE ALSO
+* Remote SM object, osm_remote_sm_construct, osm_remote_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_remote_sm_init
+* NAME
+* osm_remote_sm_init
+*
+* DESCRIPTION
+* The osm_remote_sm_init function initializes an Remote SM object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_remote_sm_init(
+ IN osm_remote_sm_t* const p_sm,
+ IN const osm_port_t* const p_port,
+ IN const ib_sm_info_t* const p_smi );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_remote_sm_t object to initialize.
+*
+* p_port
+* [in] Pointer to the Remote SM's port object.
+*
+* p_smi
+* [in] Pointer to the SMInfo attribute for this SM.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SM object was initialized successfully.
+*
+* NOTES
+* Allows calling other Remote SM methods.
+*
+* SEE ALSO
+* Remote SM object, osm_remote_sm_construct, osm_remote_sm_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REMOTE_SM_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_req_t.
+ * This object represents an object that genericly requests
+ * attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_REQ_H_
+#define _OSM_REQ_H_
+
+#include <complib/cl_atomic.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Requester
+* NAME
+* Generic Requester
+*
+* DESCRIPTION
+* The Generic Requester object encapsulates the information
+* needed to request an attribute from a node.
+*
+* The Generic Requester object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Generic Requester/osm_req_t
+* NAME
+* osm_req_t
+*
+* DESCRIPTION
+* Generic Requester structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req
+{
+ osm_mad_pool_t *p_pool;
+ osm_vl15_t *p_vl15;
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+ atomic32_t *p_sm_trans_id;
+
+} osm_req_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* p_vl15
+* Pointer to the VL15 interface.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_subn
+* Pointer to the subnet object.
+*
+* SEE ALSO
+* Generic Requester object
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_construct
+* NAME
+* osm_req_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Requester object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_construct(
+ IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to a Generic Requester object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_req_init, osm_req_destroy,
+* and osm_req_is_inited.
+*
+* Calling osm_req_construct is a prerequisite to calling any other
+* method except osm_req_init.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_init,
+* osm_req_destroy, osm_req_is_inited
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_destroy
+* NAME
+* osm_req_destroy
+*
+* DESCRIPTION
+* The osm_req_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_destroy(
+ IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Generic Requester object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_req_construct or osm_req_init.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_construct,
+* osm_req_init
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_init
+* NAME
+* osm_req_init
+*
+* DESCRIPTION
+* The osm_req_init function initializes a
+* Generic Requester object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_init(
+ IN osm_req_t* const p_req,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN atomic32_t* const p_sm_trans_id );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_subn
+* [in] Pointer to the subnet object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_sm_trans_id
+* [in] Pointer to the atomic SM transaction ID.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Generic Requester object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Requester methods.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_construct,
+* osm_req_destroy, osm_req_is_inited
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_get
+* NAME
+* osm_req_get
+*
+* DESCRIPTION
+* Starts the process to transmit a directed route request for
+* the attribute.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_get(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_path
+* [in] Pointer to the directed route path to the node
+* from which to retrieve the attribute.
+*
+* attr_id
+* [in] Attribute ID to request.
+*
+* attr_mod
+* [in] Attribute modifier for this request.
+*
+* err_msg
+* [in] Message id with which to post this MAD if an error occurs.
+*
+* p_context
+* [in] Mad wrapper context structure to be copied into the wrapper
+* context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+* IB_SUCCESS if the request was successful.
+*
+* NOTES
+* This function asynchronously requests the specified attribute.
+* The response from the node will be routed through the Dispatcher
+* to the appropriate receive controller object.
+*
+* SEE ALSO
+* Generic Requester
+*********/
+/****f* OpenSM: Generic Requester/osm_req_set
+* NAME
+* osm_req_set
+*
+* DESCRIPTION
+* Starts the process to transmit a directed route Set() request.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_set(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint8_t* const p_payload,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_path
+* [in] Pointer to the directed route path of the recipient.
+*
+* p_payload
+* [in] Pointer to the SMP payload to send.
+*
+* attr_id
+* [in] Attribute ID to request.
+*
+* attr_mod
+* [in] Attribute modifier for this request.
+*
+* err_msg
+* [in] Message id with which to post this MAD if an error occurs.
+*
+* p_context
+* [in] Mad wrapper context structure to be copied into the wrapper
+* context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+* IB_SUCCESS if the request was successful.
+*
+* NOTES
+* This function asynchronously requests the specified attribute.
+* The response from the node will be routed through the Dispatcher
+* to the appropriate receive controller object.
+*
+* SEE ALSO
+* Generic Requester
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_req_ctrl_t.
+ * This object represents a controller that calls the
+ * generic requester object to retrieve attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_REQ_CTRL_H_
+#define _OSM_REQ_CTRL_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Request Controller
+* NAME
+* Generic Request Controller
+*
+* DESCRIPTION
+* The Generic Request Controller object encapsulates the information
+* needed to request an attribute from a node.
+*
+* The Generic Request Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Generic Request Controller/osm_req_ctrl_t
+* NAME
+* osm_req_ctrl_t
+*
+* DESCRIPTION
+* Generic Request Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req_ctrl
+{
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_req_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Generic Request Controller object
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_construct
+* NAME
+* osm_req_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Request Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_construct(
+ IN osm_req_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Generic Request Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_req_ctrl_init, osm_req_ctrl_destroy,
+* and osm_req_ctrl_is_inited.
+*
+* Calling osm_req_ctrl_construct is a prerequisite to calling any other
+* method except osm_req_ctrl_init.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_init,
+* osm_req_ctrl_destroy, osm_req_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_destroy
+* NAME
+* osm_req_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_req_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_destroy(
+ IN osm_req_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Generic Request Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_req_ctrl_construct or osm_req_ctrl_init.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_construct,
+* osm_req_ctrl_init
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_init
+* NAME
+* osm_req_ctrl_init
+*
+* DESCRIPTION
+* The osm_req_ctrl_init function initializes a
+* Generic Request Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_ctrl_init(
+ IN osm_req_ctrl_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_req_ctrl_t object to initialize.
+*
+* p_req
+* [in] Pointer to a Generic Requester object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Generic Request Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Request Controller methods.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_construct,
+* Generic Requester object, osm_req_ctrl_destroy,
+* osm_req_ctrl_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_resp_t.
+ * This object represents an object that genericly requests
+ * attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_RESP_H_
+#define _OSM_RESP_H_
+
+#include <complib/cl_atomic.h>
+#include <opensm/osm_base.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Responder
+* NAME
+* Generic Responder
+*
+* DESCRIPTION
+* The Generic Responder object encapsulates the information
+* needed to respond to an attribute from a node.
+*
+* The Generic Responder object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Generic Responder/osm_resp_t
+* NAME
+* osm_resp_t
+*
+* DESCRIPTION
+* Generic Responder structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_resp
+{
+ osm_mad_pool_t *p_pool;
+ osm_vl15_t *p_vl15;
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+
+} osm_resp_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* p_vl15
+* Pointer to the VL15 interface.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_subn
+* Pointer to the subnet object.
+*
+* SEE ALSO
+* Generic Responder object
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_construct
+* NAME
+* osm_resp_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Responder object.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_construct(
+ IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to a Generic Responder object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_resp_init, osm_resp_destroy
+*
+* Calling osm_resp_construct is a prerequisite to calling any other
+* method except osm_resp_init.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_init,
+* osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_destroy
+* NAME
+* osm_resp_destroy
+*
+* DESCRIPTION
+* The osm_resp_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_destroy(
+ IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Generic Responder object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_resp_construct or osm_resp_init.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_construct,
+* osm_resp_init
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_init
+* NAME
+* osm_resp_init
+*
+* DESCRIPTION
+* The osm_resp_init function initializes a
+* Generic Responder object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_init(
+ IN osm_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_resp_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_subn
+* [in] Pointer to the subnet object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Generic Responder object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Responder methods.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_construct,
+* osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_send
+* NAME
+* osm_resp_send
+*
+* DESCRIPTION
+* Starts the process to transmit a directed route response.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_send(
+ IN const osm_resp_t* const p_resp,
+ IN const osm_madw_t* const p_req_madw,
+ IN const ib_net16_t status,
+ IN const uint8_t* const p_payload );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_resp_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper object for the requesting MAD
+* to which this response is generated.
+*
+* status
+* [in] Status for this response.
+*
+* p_payload
+* [in] Pointer to the payload of the response MAD.
+*
+* RETURN VALUES
+* IB_SUCCESS if the response was successful.
+*
+* NOTES
+*
+* SEE ALSO
+* Generic Responder
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RESP_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SA_H_
+#define _OSM_SA_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_stats.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_subnet.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA
+* NAME
+* SA
+*
+* DESCRIPTION
+* The SA object encapsulates the information needed by the
+* OpenSM to instantiate a subnet administrator. The OpenSM allocates
+* one SA object per subnet manager.
+*
+* The SA object is thread safe.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+* Anil Keshavamurthy, Intel
+*
+*********/
+
+/****d* OpenSM: SA/osm_sa_state_t
+* NAME
+* osm_sa_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of SA object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sa_state
+{
+ OSM_SA_STATE_INIT = 0,
+ OSM_SA_STATE_READY
+
+} osm_sa_state_t;
+/***********/
+
+/****s* OpenSM: SM/osm_sa_t
+* NAME
+* osm_sa_t
+*
+* DESCRIPTION
+* Subnet Administrator structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa
+{
+ osm_sa_state_t state;
+ osm_subn_t *p_subn;
+ osm_vendor_t *p_vendor;
+ osm_log_t *p_log;
+ osm_mad_pool_t *p_mad_pool;
+ cl_dispatcher_t *p_disp;
+ cl_plock_t *p_lock;
+ atomic32_t sa_trans_id;
+ osm_sa_mad_ctrl_t mad_ctrl;
+ osm_sa_resp_t resp;
+ osm_cpi_rcv_t cpi_rcv;
+ osm_cpi_rcv_ctrl_t cpi_rcv_ctrl;
+ osm_nr_rcv_t nr_rcv;
+ osm_nr_rcv_ctrl_t nr_rcv_ctrl;
+ osm_pir_rcv_t pir_rcv;
+ osm_pir_rcv_ctrl_t pir_rcv_ctrl;
+ osm_lr_rcv_t lr_rcv;
+ osm_lr_rcv_ctrl_t lr_rcv_ctrl;
+ osm_pr_rcv_t pr_rcv;
+ osm_pr_rcv_ctrl_t pr_rcv_ctrl;
+ osm_smir_rcv_t smir_rcv;
+ osm_smir_ctrl_t smir_ctrl;
+ osm_mcmr_recv_t mcmr_rcv;
+ osm_mcmr_rcv_ctrl_t mcmr_rcv_ctlr;
+ osm_sr_rcv_t sr_rcv;
+ osm_sr_rcv_ctrl_t sr_rcv_ctrl;
+
+ /* InformInfo Receiver */
+ osm_infr_rcv_t infr_rcv;
+ osm_infr_rcv_ctrl_t infr_rcv_ctrl;
+
+ /* VL Arbitrartion Query */
+ osm_vlarb_rec_rcv_t vlarb_rec_rcv;
+ osm_vlarb_rec_rcv_ctrl_t vlarb_rec_rcv_ctrl;
+
+ /* SLtoVL Map Query */
+ osm_slvl_rec_rcv_t slvl_rec_rcv;
+ osm_slvl_rec_rcv_ctrl_t slvl_rec_rcv_ctrl;
+
+ /* P_Key table Query */
+ osm_pkey_rec_rcv_t pkey_rec_rcv;
+ osm_pkey_rec_rcv_ctrl_t pkey_rec_rcv_ctrl;
+
+ /* LinearForwardingTable Query */
+ osm_lftr_rcv_t lftr_rcv;
+ osm_lftr_rcv_ctrl_t lftr_rcv_ctrl;
+
+} osm_sa_t;
+/*
+* FIELDS
+* state
+ State of this SA object
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_vendor
+* Pointer to the vendor specific interfaces object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mad_pool
+* Pointer to the MAD pool.
+*
+* p_disp
+* Pointer to dispatcher
+*
+* p_lock
+* Pointer to Lock for serialization
+*
+* sa_trans_id
+* Transaction ID
+*
+* mad_ctrl
+* Mad Controller
+*
+* resp
+* Response object
+*
+* nr
+*
+* nr_ctrl
+*
+* pir_rcv
+*
+* pir_rcv_ctrl
+*
+* lr
+*
+* lr_ctrl
+*
+* pr
+*
+* pr_ctrl
+*
+* smir
+*
+* smir_ctrl
+*
+* SEE ALSO
+* SM object
+*********/
+
+/****f* OpenSM: SA/osm_sa_construct
+* NAME
+* osm_sa_construct
+*
+* DESCRIPTION
+* This function constructs an SA object.
+*
+* SYNOPSIS
+*/
+void osm_sa_construct(
+ IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to a SA object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sa_init, osm_sa_destroy, and osm_sa_is_inited.
+*
+* Calling osm_sa_construct is a prerequisite to calling any other
+* method except osm_sa_init.
+*
+* SEE ALSO
+* SA object, osm_sa_init, osm_sa_destroy, osm_sa_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_shutdown
+* NAME
+* osm_sa_shutdown
+*
+* DESCRIPTION
+* The osm_sa_shutdown function shutdowns an SA, unregistering from all
+* dispatcher messages and unbinding the QP1 mad service
+*
+* SYNOPSIS
+*/
+void osm_sa_shutdown(
+ IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to a SA object to shutdown.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* SEE ALSO
+* SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_destroy
+* NAME
+* osm_sa_destroy
+*
+* DESCRIPTION
+* The osm_sa_destroy function destroys an SA, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sa_destroy(
+ IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to a SA object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified SA object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_sa_construct or
+* osm_sa_init.
+*
+* SEE ALSO
+* SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_init
+* NAME
+* osm_sa_init
+*
+* DESCRIPTION
+* The osm_sa_init function initializes a SA object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sa_init(
+ IN osm_sm_t* const p_sm,
+ IN osm_sa_t* const p_sa,
+ IN osm_subn_t* const p_subn,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to an osm_sa_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_vendor
+* [in] Pointer to the vendor specific interfaces object.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_stats
+* [in] Pointer to the statistics object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SA object was initialized successfully.
+*
+* NOTES
+* Allows calling other SA methods.
+*
+* SEE ALSO
+* SA object, osm_sa_construct, osm_sa_destroy,
+* osm_sa_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_is_inited
+* NAME
+* osm_sa_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_sa_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sa_is_inited(
+ IN const osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to an osm_sa_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_sa_construct or osm_sa_init must be called before using
+* this function.
+*
+* SEE ALSO
+* SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_bind
+* NAME
+* osm_sa_bind
+*
+* DESCRIPTION
+* Binds the SA object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_bind(
+ IN osm_sa_t* const p_sa,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to an osm_sa_t object to bind.
+*
+* port_guid
+* [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given SA object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SA/osm_sa_add_well_known_mc_record
+* NAME
+* osm_sa_add_well_known_mc_record
+*
+* DESCRIPTION
+* Adds the well known Multicast group to the SA database. This
+* should be called by SM before programming the switches and after
+* SA has been initialized
+*
+* SYNOPSIS
+*/
+
+void
+osm_sa_add_well_known_mc_record(
+ osm_mcmr_recv_t* const p_ctrl,
+ const ib_member_rec_t * const p_well_know_mc_rec);
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_recv_t object.
+*
+* p_well_know_mc_rec
+* [in] pointer to ib_member_rec_t structure.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* Called by SM after SA has been initialized and before programming the switches
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: SA/osm_sa_create_template_record_ipoib
+* NAME
+* osm_sa_create_template_record_ipoib
+*
+* DESCRIPTION
+* Creates the well known MC record and calls osm_sa_add_well_known_mc_record. This
+* should be called by SM before programming the switches and after
+* SA has been initialized
+*
+* SYNOPSIS
+*/
+void
+osm_sa_create_template_record_ipoib(
+ IN osm_sa_t* const p_sa,
+ IN const osm_subn_opt_t* const p_opt );
+
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to an osm_sa_t object.
+*
+* p_opt
+* [in] pointer to cmd line option structure.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* Called by SM after SA has been initialized and before programming the switches
+*
+* SEE ALSO
+*********/
+
+/****g* OpenSM: SA/osm_ipoib_mgid
+* NAME
+* osm_ipoib_mgid
+*
+* DESCRIPTION
+* The MGID of the IPoIB Multicast Group
+*
+* SYNOPSIS
+*/
+extern ib_gid_t osm_ipoib_mgid;
+/*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+#ifndef _OSM_CPI_H_
+#define _OSM_CPI_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/ClassPort Info Receiver
+* NAME
+* ClassPort Info Receiver
+*
+* DESCRIPTION
+* The ClassPort Info Receiver object encapsulates the information
+* needed to receive the ClassPortInfo request from a node.
+*
+* The ClassPort Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_t
+* NAME
+* osm_cpi_rcv_t
+*
+* DESCRIPTION
+* ClassPort Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_cpi_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* ClassPort Info Receiver object
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_construct
+* NAME
+* osm_cpi_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a ClassPort Info Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_construct(
+ IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a ClassPort Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*
+* Calling osm_cpi_rcv_construct is a prerequisite to calling any other
+* method except osm_cpi_rcv_init.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_destroy
+* NAME
+* osm_cpi_rcv_destroy
+*
+* DESCRIPTION
+* The osm_cpi_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_destroy(
+ IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* ClassPort Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_cpi_rcv_construct or osm_cpi_rcv_init.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_construct,
+* osm_cpi_rcv_init
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_init
+* NAME
+* osm_cpi_rcv_init
+*
+* DESCRIPTION
+* The osm_cpi_rcv_init function initializes a
+* ClassPort Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_cpi_rcv_init(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the ClassPort Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other ClassPort Info Receiver methods.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_construct,
+* osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_process
+* NAME
+* osm_cpi_rcv_process
+*
+* DESCRIPTION
+* Process the ClassPortInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_process(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the ClassPortInfo attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the ClassPortInfo processing was successful.
+*
+* NOTES
+* This function processes a ClassPortInfo attribute.
+*
+* SEE ALSO
+* ClassPort Info Receiver, ClassPort Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPI_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+#ifndef _OSM_CPICTRL_H_
+#define _OSM_CPICTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_class_port_info.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Class Port Info Receive Controller
+* NAME
+* Class Port Info Receive Controller
+*
+* DESCRIPTION
+* The Class Port Info Receive Controller object encapsulates
+* the information requested by the ClassPortInfo attribute.
+*
+* The ClassPortInfo Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: ClassPort Info Receive Controller/osm_cpi_rcv_ctrl_t
+* NAME
+* osm_cpi_rcv_ctrl_t
+*
+* DESCRIPTION
+* ClassPort Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv_ctrl
+{
+ osm_cpi_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_cpi_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the ClassPort Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object
+* Class Port Info Receiver object
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_construct
+* NAME
+* osm_cpi_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Class Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_construct(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Class Port Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_cpi_rcv_ctrl_init, osm_cpi_rcv_ctrl_destroy,
+* and osm_cpi_rcv_ctrl_is_inited.
+*
+* Calling osm_cpi_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_init,
+* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_destroy
+* NAME
+* osm_cpi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_cpi_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_destroy(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Class Port Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_init
+* NAME
+* osm_cpi_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_cpi_rcv_ctrl_init function initializes a
+* Class Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_cpi_rcv_ctrl_init(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_cpi_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Class Port Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Class Port Info Receive Controller methods.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_is_inited
+* NAME
+* osm_cpi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_cpi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_cpi_rcv_ctrl_is_inited(
+ IN const osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_cpi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPICTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_infr_rcv_t.
+ * This object represents the InformInfoRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SA_INFR_H_
+#define _OSM_SA_INFR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/InformInfo Receiver
+* NAME
+* InformInfo Receiver
+*
+* DESCRIPTION
+* The InformInfo Receiver object encapsulates the information
+* needed to receive the InformInfo request from a node.
+*
+* The InformInfo Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: InformInfo Receiver/osm_infr_rcv_t
+* NAME
+* osm_infr_rcv_t
+*
+* DESCRIPTION
+* InformInfo Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+} osm_infr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the osm_sa_resp_t object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_construct
+* NAME
+* osm_infr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a InformInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_construct(
+ IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a InformInfo Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_infr_rcv_init, osm_infr_rcv_destroy
+*
+* Calling osm_infr_rcv_construct is a prerequisite to calling any other
+* method except osm_infr_rcv_init.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_init, osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_destroy
+* NAME
+* osm_infr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_infr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_destroy(
+ IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* InformInfo Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_infr_rcv_construct or osm_infr_rcv_init.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_construct,
+* osm_infr_rcv_init
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_init
+* NAME
+* osm_infr_rcv_init
+*
+* DESCRIPTION
+* The osm_infr_rcv_init function initializes a
+* InformInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_infr_rcv_init(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the InformInfo Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other InformInfo Receiver methods.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_construct,
+* osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_process
+* NAME
+* osm_infr_rcv_process
+*
+* DESCRIPTION
+* Process the InformInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's InformInfo attribute.
+* NOTES
+* This function processes a InformInfo attribute.
+*
+* SEE ALSO
+* InformInfo Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_INFR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_infr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA InfromInfo
+ * Set method attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_INFR_RCV_CTRL_H_
+#define _OSM_INFR_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_inform.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/InformInfo Receive Controller
+* NAME
+* InformInfo Receive Controller
+*
+* DESCRIPTION
+* The InformInfo Receive Controller object encapsulates
+* the information needed to receive the InformInfo attribute from a node.
+*
+* The InformInfo Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_t
+* NAME
+* osm_infr_rcv_ctrl_t
+*
+* DESCRIPTION
+* InformInfo Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv_ctrl
+{
+ osm_infr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_infr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the InformInfo Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* InformInfo Receive Controller object
+* InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_construct
+* NAME
+* osm_infr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a InformInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_construct(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a InformInfo Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_infr_rcv_ctrl_init, osm_infr_rcv_ctrl_destroy,
+* and osm_infr_rcv_ctrl_is_inited.
+*
+* Calling osm_infr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_init,
+* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_destroy
+* NAME
+* osm_infr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_infr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_destroy(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* InformInfo Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_init
+* NAME
+* osm_infr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_infr_rcv_ctrl_init function initializes a
+* InformInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_infr_rcv_ctrl_init(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl,
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_infr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the InformInfo Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other InformInfo Receive Controller methods.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_is_inited
+* NAME
+* osm_infr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_infr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_infr_rcv_ctrl_is_inited(
+ IN const osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_infr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_INFR_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lftr_rcv_t.
+ * This object represents the LinearForwardingTable Receiver object.
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LFTR_H_
+#define _OSM_LFTR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table Receiver
+* NAME
+* Linear Forwarding Table Receiver
+*
+* DESCRIPTION
+* The Linear Forwarding Table Receiver object encapsulates the information
+* needed to receive the LinearForwardingTable attribute from a switch node.
+*
+* The Linear Forwarding Table Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+/****s* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_t
+* NAME
+* osm_lftr_rcv_t
+*
+* DESCRIPTION
+* Linear Forwarding Table Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft
+{
+ osm_subn_t* p_subn;
+ osm_stats_t* p_stats;
+ osm_sa_resp_t* p_resp;
+ osm_mad_pool_t* p_mad_pool;
+ osm_log_t* p_log;
+ cl_plock_t* p_lock;
+ cl_qlock_pool_t pool;
+} osm_lftr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_construct
+* NAME
+* osm_lftr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Linear Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_construct(
+ IN osm_lftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Linear Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lftr_rcv_init, osm_lftr_rcv_destroy
+*
+* Calling osm_lftr_rcv_construct is a prerequisite to calling any other
+* method except osm_lftr_rcv_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_init,
+* osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_destroy
+* NAME
+* osm_lftr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lftr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_destroy(
+ IN osm_lftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Linear Forwarding Table Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lftr_rcv_construct or osm_lftr_rcv_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct,
+* osm_lftr_rcv_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_init
+* NAME
+* osm_lftr_rcv_init
+*
+* DESCRIPTION
+* The osm_lftr_rcv_init function initializes a
+* Linear Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_init(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lftr_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Linear Forwarding Table Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Linear Forwarding Table Receiver methods.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct,
+* osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_process
+* NAME
+* osm_lftr_rcv_process
+*
+* DESCRIPTION
+* Process the LinearForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_process(
+ IN osm_lftr_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lftr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the switch node's LinearForwardingTable attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LinearForwardingTable processing was successful.
+*
+* NOTES
+* This function processes a LinearForwardingTable attribute.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver, Linear Forwarding Table Response
+* Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lftr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * LinearForwardingTable attribute from a switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LFTR_RCV_CTRL_H_
+#define _OSM_LFTR_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_lft_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table Receive Controller
+* NAME
+* Linear Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+* The Linear Forwarding Table Receive Controller object encapsulates
+* the information needed to receive the LinearFowrardingTable attribute
+* from a switch node.
+*
+* The Linear Forwarding Table Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_t
+* NAME
+* osm_lftr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Linear Forwarding Table Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lftr_rcv_ctrl
+{
+ osm_lftr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lftr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Linear Forwarding Table Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object
+* Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_construct
+* NAME
+* osm_lftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Linear Forwarding Table Receive
+* Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_construct(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Linear Forwarding Table Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lftr_rcv_ctrl_init, osm_lftr_rcv_ctrl_destroy
+*
+* Calling osm_lftr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_init,
+* osm_lftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_destroy
+* NAME
+* osm_lftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lftr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_destroy(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Linear Forwarding Table Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lftr_rcv_ctrl_construct or osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_construct,
+* osm_lftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_init
+* NAME
+* osm_lftr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lftr_rcv_ctrl_init function initializes a
+* Linear Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_ctrl_init(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lftr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lftr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Linear Forwarding Table Receive Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other Linear Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object,
+* osm_lftr_rcv_ctrl_construct, osm_lftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lr_rcv_t.
+ * This object represents the Link Record Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LR_RCV_H_
+#define _OSM_LR_RCV_H_
+
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Record Receiver
+* NAME
+* Link Record Receiver
+*
+* DESCRIPTION
+* The Link Record Receiver object encapsulates the information
+* needed to receive the Link Record attribute from a node.
+*
+* The Link Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: Link Record Receiver/osm_lr_rcv_t
+* NAME
+* osm_lr_rcv_t
+*
+* DESCRIPTION
+* Link Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t lr_pool;
+
+} osm_lr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* lr_pool
+* Pool of link record objects used to generate the query response.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_construct
+* NAME
+* osm_lr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Link Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_construct(
+ IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Link Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lr_rcv_init, osm_lr_rcv_destroy
+*
+* Calling osm_lr_rcv_construct is a prerequisite to calling any other
+* method except osm_lr_rcv_init.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_destroy
+* NAME
+* osm_lr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_destroy(
+ IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Link Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lr_rcv_construct or osm_lr_rcv_init.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_construct,
+* osm_lr_rcv_init
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_init
+* NAME
+* osm_lr_rcv_init
+*
+* DESCRIPTION
+* The osm_lr_rcv_init function initializes a
+* Link Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_init(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lr_rcv_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the SA Responder object.
+*
+* p_mad_pool
+* [in] Pointer to the mad pool.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Link Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_construct, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_process
+* NAME
+* osm_lr_rcv_process
+*
+* DESCRIPTION
+* Process the Link Record attribute.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_process(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's Link Record attribute.
+*
+* NOTES
+* This function processes a Link Record attribute.
+*
+* SEE ALSO
+* Link Record Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Link Record
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_LR_CTRL_H_
+#define _OSM_LR_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_link_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Recrod Receive Controller
+* NAME
+* Link Recrod Receive Controller
+*
+* DESCRIPTION
+* The Link Recrod Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Link Recrod Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_t
+* NAME
+* osm_lr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Link Recrod Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv_ctrl
+{
+ osm_lr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Link Recrod Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Link Record Receive Controller object
+* Link Record Receiver object
+*********/
+
+/****f* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_construct
+* NAME
+* osm_lr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Link Recrod Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_construct(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Link Recrod Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lr_rcv_ctrl_init, osm_lr_rcv_ctrl_destroy,
+* and osm_lr_rcv_ctrl_is_inited.
+*
+* Calling osm_lr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Link Recrod Receive Controller object, osm_lr_rcv_ctrl_init,
+* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_destroy
+* NAME
+* osm_lr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_destroy(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Link Recrod Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Link Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_init
+* NAME
+* osm_lr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lr_rcv_ctrl_init function initializes a
+* Link Recrod Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Link Recrod Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Recrod Receive Controller methods.
+*
+* SEE ALSO
+* Link Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_is_inited
+* NAME
+* osm_lr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_lr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_lr_rcv_ctrl_is_inited(
+ IN const osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Link Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_mad_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SA_MAD_CTRL_H_
+#define _OSM_SA_MAD_CTRL_H_
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_response.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA MAD Controller
+* NAME
+* SA MAD Controller
+*
+* DESCRIPTION
+* The SA MAD Controller object encapsulates
+* the information needed to receive MADs from the transport layer.
+*
+* The SA MAD Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_t
+* NAME
+* osm_sa_mad_ctrl_t
+*
+* DESCRIPTION
+* SA MAD Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa_mad_ctrl
+{
+ osm_log_t *p_log;
+ osm_mad_pool_t *p_mad_pool;
+ osm_vendor_t *p_vendor;
+ osm_bind_handle_t h_bind;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+ osm_stats_t *p_stats;
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+} osm_sa_mad_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_mad_pool
+* Pointer to the MAD pool.
+*
+* p_vendor
+* Pointer to the vendor specific interfaces object.
+*
+* h_bind
+* Bind handle returned by the transport layer.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_resp
+* Pointer to the SA response manager
+*
+* SEE ALSO
+* SA MAD Controller object
+* SA MADr object
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_construct
+* NAME
+* osm_sa_mad_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SA MAD Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sa_mad_ctrl_construct(
+ IN osm_sa_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SA MAD Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sa_mad_ctrl_init, osm_sa_mad_ctrl_destroy,
+* and osm_sa_mad_ctrl_is_inited.
+*
+* Calling osm_sa_mad_ctrl_construct is a prerequisite to calling any other
+* method except osm_sa_mad_ctrl_init.
+*
+* SEE ALSO
+* SA MAD Controller object, osm_sa_mad_ctrl_init,
+* osm_sa_mad_ctrl_destroy, osm_sa_mad_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_destroy
+* NAME
+* osm_sa_mad_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sa_mad_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sa_mad_ctrl_destroy(
+ IN osm_sa_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SA MAD Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sa_mad_ctrl_construct or osm_sa_mad_ctrl_init.
+*
+* SEE ALSO
+* SA MAD Controller object, osm_sa_mad_ctrl_construct,
+* osm_sa_mad_ctrl_init
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_init
+* NAME
+* osm_sa_mad_ctrl_init
+*
+* DESCRIPTION
+* The osm_sa_mad_ctrl_init function initializes a
+* SA MAD Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sa_mad_ctrl_init(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the response SA manager object
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vendor
+* [in] Pointer to the vendor specific interfaces object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_stats
+* [in] Pointer to the OpenSM stastics block.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SA MAD Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SA MAD Controller methods.
+*
+* SEE ALSO
+* SA MAD Controller object, osm_sa_mad_ctrl_construct,
+* osm_sa_mad_ctrl_destroy, osm_sa_mad_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_bind
+* NAME
+* osm_sa_mad_ctrl_bind
+*
+* DESCRIPTION
+* Binds the SA MAD Controller object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_mad_ctrl_bind(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+* port_guid
+* [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given SA MAD Controller object can only be bound to one
+* port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_unbind
+* NAME
+* osm_sa_mad_ctrl_unbind
+*
+* DESCRIPTION
+* Un-Binds the SA MAD Controller object from the IB port
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_mad_ctrl_unbind(
+ IN osm_sa_mad_ctrl_t* const p_ctrl);
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given SA MAD Controller should be previously bound to IB
+* port.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_get_bind_handle
+* NAME
+* osm_sa_mad_ctrl_get_bind_handle
+*
+* DESCRIPTION
+* Returns the bind handle.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_sa_mad_ctrl_get_bind_handle(
+ IN const osm_sa_mad_ctrl_t* const p_ctrl )
+{
+ return( p_ctrl->h_bind );
+}
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sa_mad_ctrl_t object.
+*
+* RETURN VALUES
+* Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE
+* if no port has been bound.
+*
+* NOTES
+* A given SA MAD Controller object can only be bound to one
+* port at a time.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_MAD_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcmr_recv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+
+#ifndef _OSM_MCMR_H_
+#define _OSM_MCMR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receiver
+* NAME
+* Node Info Receiver
+*
+* DESCRIPTION
+* The Node Info Receiver object encapsulates the information
+* needed to receive the NodeRecord attribute from a node.
+*
+* The Node Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receiver/osm_mcmr_recv_t
+* NAME
+* osm_mcmr_recv_t
+*
+* DESCRIPTION
+* Node Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+
+typedef struct _osm_mcmr
+{
+ osm_subn_t *p_subn;
+ osm_sm_t *p_sm;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ uint16_t mlid_ho;
+ cl_qlock_pool_t pool;
+} osm_mcmr_recv_t;
+
+
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_rcv_construct
+* NAME
+* osm_mcmr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_construct(
+ IN osm_mcmr_recv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcmr_rcv_init, osm_mcmr_rcv_destroy
+*
+* Calling osm_mcmr_rcv_construct is a prerequisite to calling any other
+* method except osm_mcmr_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_mcmr_init,
+* osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_rcv_destroy
+* NAME
+* osm_mcmr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_destroy(
+ IN osm_mcmr_recv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcmr_rcv_construct or osm_mcmr_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_mcmr_rcv_construct,
+* osm_mcmr_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_rcv_init
+* NAME
+* osm_mcmr_init
+*
+* DESCRIPTION
+* The osm_mcmr_init function initializes a
+* Node Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_mcmr_recv_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_sm
+* [in] pointer to osm_sm_t object
+* p_ctrl
+* [in] Pointer to an osm_mcmr_recv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_mcmr_rcv_construct,
+* osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_mcmrocess
+* NAME
+* osm_mcmr_mcmrocess
+*
+* DESCRIPTION
+* Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_process(
+ IN osm_mcmr_recv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_recv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+* This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+* Node Info Receiver, Node Info Response Controller
+*********/
+
+
+
+/****f* OpenSM: MC Member record Receiver/osm_mcmr_rcv_create_new_mgrp
+* NAME
+* osm_mcmr_rcv_create_new_mgrp
+*
+* DESCRIPTION
+* Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN uint64_t comp_mask,
+ IN const ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+* p_mcmr
+* [in] Pointer to an osm_mcmr_recv_t object.
+* p_recvd_mcmember_rec
+* [in] Received Multicast member record
+*
+* pp_mgrp
+* [out] pointer the osm_mgrp_t object
+*
+* RETURN VALUES
+* IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*
+*********/
+
+#define JOIN_MC_COMP_MASK (IB_MCR_COMPMASK_MGID | \
+ IB_MCR_COMPMASK_PORT_GID | \
+ IB_MCR_COMPMASK_JOIN_STATE)
+
+#define REQUIRED_MC_CREATE_COMP_MASK (IB_MCR_COMPMASK_MGID | \
+ IB_MCR_COMPMASK_PORT_GID | \
+ IB_MCR_COMPMASK_JOIN_STATE | \
+ IB_MCR_COMPMASK_QKEY | \
+ IB_MCR_COMPMASK_TCLASS | \
+ IB_MCR_COMPMASK_PKEY | \
+ IB_MCR_COMPMASK_FLOW | \
+ IB_MCR_COMPMASK_SL)
+
+/****d* OpenSM: MC Member record Receiver/OSM_DEFAULT_MGRP_MTU
+* Name
+* OSM_DEFAULT_MGRP_MTU
+*
+* DESCRIPTION
+* Default MTU used for new MGRP creation (256 bytes)
+* Note it includes the MTUSelector which is set to "Greater Then"
+* But this means really greater or equal ...
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_MTU 0x01
+/***********/
+
+/****d* OpenSM: MC Member record Receiver/OSM_DEFAULT_MGRP_RATE
+* Name
+* OSM_DEFAULT_MGRP_RATE
+*
+* DESCRIPTION
+* Default RATE used for new MGRP creation (10Gb/sec)
+* Note it includes the RateSelector which is set to "Greater Then"
+* But this means really greater or equal ...
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_RATE 0x03
+/***********/
+
+/* These Component Mask fields comply with IB Spec 1.0.M3 */
+#define MC_FULL_MEMBER 0x1
+#define MC_NON_MEMBER 0x2
+#define MC_SENDONLY_NON_MEMBER 0x4
+
+END_C_DECLS
+
+#endif /* _OSM_MCMR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcmr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MCMRCTRL_H
+#define _OSM_MCMRCTRL_H
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mcmember_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receive Controller
+* NAME
+* Node Info Receive Controller
+*
+* DESCRIPTION
+* The Node Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_t
+* NAME
+* osm_mcmr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmr_rcv_ctrl
+{
+ osm_mcmr_recv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_mcmr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Info Receive Controller object
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_construct
+* NAME
+* osm_mcmr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_construct(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcmr_rcv_ctrl_init, osm_mcmr_rcv_ctrl_destroy,
+* and osm_mcmr_ctrl_is_inited.
+*
+* Calling osm_mcmr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_mcmr_rcv_ctrl_init,
+* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_destroy
+* NAME
+* osm_mcmr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_destroy(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_init
+* NAME
+* osm_mcmr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_ctrl_init function initializes a
+* Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_ctrl_init(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mcmr_recv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_mcmr_ctrl_is_inited
+* NAME
+* osm_mcmr_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_mcmr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcmr_ctrl_is_inited(
+ IN const osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMRCTRL_H */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nr_rcv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_NR_H_
+#define _OSM_NR_H_
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Record Receiver
+* NAME
+* Node Record Receiver
+*
+* DESCRIPTION
+* The Node Record Receiver object encapsulates the information
+* needed to receive the NodeRecord attribute from a node.
+*
+* The Node record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Node Record Receiver/osm_nr_rcv_t
+* NAME
+* osm_nr_rcv_t
+*
+* DESCRIPTION
+* Node Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_recv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_nr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable node record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_construct
+* NAME
+* osm_nr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Record Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_construct(
+ IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Node Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nr_rcv_init, osm_nr_rcv_destroy
+*
+* Calling osm_nr_rcv_construct is a prerequisite to calling any other
+* method except osm_nr_rcv_init.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_destroy
+* NAME
+* osm_nr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_nr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_destroy(
+ IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nr_rcv_construct or osm_nr_rcv_init.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_construct,
+* osm_nr_rcv_init
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_init
+* NAME
+* osm_nr_rcv_init
+*
+* DESCRIPTION
+* The osm_nr_rcv_init function initializes a
+* Node Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_init(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the SA Responder object.
+*
+* p_mad_pool
+* [in] Pointer to the mad pool.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Node Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_construct, osm_nr_rcv_destroy
+*********/
+
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_process
+* NAME
+* osm_nr_rcv_process
+*
+* DESCRIPTION
+* Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_process(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeRecord attribute.
+*
+* NOTES
+* This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+* Node Record Receiver, Node Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * record from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_NR_CTRL_H_
+#define _OSM_NR_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Record Receive Controller
+* NAME
+* Node Record Receive Controller
+*
+* DESCRIPTION
+* The Node Record Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_t
+* NAME
+* osm_nr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_ctrl
+{
+ osm_nr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_nr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Record Receive Controller object
+* Node Record Receiver object
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_construct
+* NAME
+* osm_nr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_construct(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nr_rcv_ctrl_init, osm_nr_rcv_ctrl_destroy,
+*
+* Calling osm_nr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_init,
+* osm_nr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_destroy
+* NAME
+* osm_nr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_nr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_destroy(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nr_rcv_ctrl_construct or osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+* osm_nr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_init
+* NAME
+* osm_nr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_nr_rcv_ctrl_init function initializes a
+* Node Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_ctrl_init(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl,
+ IN osm_nr_rcv_t* const p_nr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_nr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Record Receive Controller methods.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+* osm_nr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pr_rcv_t.
+ * This object represents the PathRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PR_H_
+#define _OSM_PR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Path Record Receiver
+* NAME
+* Path Record Receiver
+*
+* DESCRIPTION
+* The Path Record Receiver object encapsulates the information
+* needed to receive the PathRecord request from a node.
+*
+* The Path Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Path Record Receiver/osm_pr_rcv_t
+* NAME
+* osm_pr_rcv_t
+*
+* DESCRIPTION
+* Path Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pr_pool;
+
+} osm_pr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pr_pool
+* Pool of path record objects used to generate query reponses.
+*
+* SEE ALSO
+* Path Record Receiver object
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_construct
+* NAME
+* osm_pr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Path Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_construct(
+ IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Path Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pr_rcv_init, osm_pr_rcv_destroy
+*
+* Calling osm_pr_rcv_construct is a prerequisite to calling any other
+* method except osm_pr_rcv_init.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_init, osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_destroy
+* NAME
+* osm_pr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_destroy(
+ IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Path Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pr_rcv_construct or osm_pr_rcv_init.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_construct,
+* osm_pr_rcv_init
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_init
+* NAME
+* osm_pr_rcv_init
+*
+* DESCRIPTION
+* The osm_pr_rcv_init function initializes a
+* Path Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pr_rcv_init(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Path Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Path Record Receiver methods.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_construct,
+* osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_process
+* NAME
+* osm_pr_rcv_process
+*
+* DESCRIPTION
+* Process the PathRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_process(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's PathRecord attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the PathRecord processing was successful.
+*
+* NOTES
+* This function processes a PathRecord attribute.
+*
+* SEE ALSO
+* Path Record Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PRCTRL_H_
+#define _OSM_PRCTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_path_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receive Controller
+* NAME
+* Node Info Receive Controller
+*
+* DESCRIPTION
+* The Node Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_t
+* NAME
+* osm_pr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv_ctrl
+{
+ osm_pr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Info Receive Controller object
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_construct
+* NAME
+* osm_pr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_construct(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pr_rcv_ctrl_init, osm_pr_rcv_ctrl_destroy,
+* and osm_pr_rcv_ctrl_is_inited.
+*
+* Calling osm_pr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_pr_rcv_ctrl_init,
+* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_destroy
+* NAME
+* osm_pr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_destroy(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_init
+* NAME
+* osm_pr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pr_rcv_ctrl_init function initializes a
+* Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pr_rcv_ctrl_init(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl,
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_is_inited
+* NAME
+* osm_pr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pr_rcv_ctrl_is_inited(
+ IN const osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PRCTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+#ifndef _OSM_PKEY_REC_RCV_H_
+#define _OSM_PKEY_REC_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Record Receiver
+* NAME
+* P_Key Record Receiver
+*
+* DESCRIPTION
+* The P_Key Record Receiver object encapsulates the information
+* needed to handle P_Key Record query from a SA.
+*
+* The P_Key Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+/****s* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_t
+* NAME
+* osm_pkey_rec_rcv_t
+*
+* DESCRIPTION
+* P_Key Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_pkey_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable P_Key Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+* osm_pkey_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_construct(
+ IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a P_Key Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rec_rcv_init, osm_pkey_rec_rcv_destroy
+*
+* Calling osm_pkey_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_init,
+* osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_destroy
+* NAME
+* osm_pkey_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_destroy(
+ IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rec_rcv_construct or osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+* osm_pkey_rec_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_init
+* NAME
+* osm_pkey_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_init function initializes a
+* P_Key Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Record Receiver methods.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+* osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_process
+* NAME
+* osm_pkey_rec_rcv_process
+*
+* DESCRIPTION
+* Process the P_Key Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_process(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the P_Key Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA P_Key Record attribute.
+*
+* SEE ALSO
+* P_Key Record Receiver, P_Key Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_REC_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+#ifndef _OSM_PKEY_REC_CTRL_H_
+#define _OSM_PKEY_REC_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_pkey_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Record Receive Controller
+* NAME
+* P_Key Record Receive Controller
+*
+* DESCRIPTION
+* The P_Key Record Receive Controller object encapsulates
+* the information needed to handle P_Key record query from SA client.
+*
+* The P_Key Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+/****s* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_t
+* NAME
+* osm_pkey_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* P_Key Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv_ctrl
+{
+ osm_pkey_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pkey_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the P_Key Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object
+* P_Key Record Receiver object
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_construct
+* NAME
+* osm_pkey_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_construct(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rec_rcv_ctrl_init, osm_pkey_rec_rcv_ctrl_destroy
+*
+* Calling osm_pkey_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_init,
+* osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_destroy
+* NAME
+* osm_pkey_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_destroy(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rec_rcv_ctrl_construct or osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+* osm_pkey_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_init
+* NAME
+* osm_pkey_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_ctrl_init function initializes a
+* P_Key Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rec_rcv_ctrl_init(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Record Receive Controller methods.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+* osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_REC_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pir_rcv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PIR_RCV_H_
+#define _OSM_PIR_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/PortInfo Record Receiver
+* NAME
+* PortInfo Record Receiver
+*
+* DESCRIPTION
+* The PortInfo Record Receiver object encapsulates the information
+* needed to receive the NodeRecord attribute from a node.
+*
+* The PortInfo Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: PortInfo Record Receiver/osm_pir_rcv_t
+* NAME
+* osm_pir_rcv_t
+*
+* DESCRIPTION
+* PortInfo Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_pir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable PortInfo Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_construct
+* NAME
+* osm_pir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a PortInfo Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_construct(
+ IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a PortInfo Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pir_rcv_init, osm_pir_rcv_destroy
+*
+* Calling osm_pir_rcv_construct is a prerequisite to calling any other
+* method except osm_pir_rcv_init.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_init,
+* osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_destroy
+* NAME
+* osm_pir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_destroy(
+ IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* PortInfo Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pir_rcv_construct or osm_pir_rcv_init.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_construct,
+* osm_pir_rcv_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_init
+* NAME
+* osm_pir_rcv_init
+*
+* DESCRIPTION
+* The osm_pir_rcv_init function initializes a
+* PortInfo Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pir_rcv_init(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfo Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other PortInfo Record Receiver methods.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_construct,
+* osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_process
+* NAME
+* osm_pir_rcv_process
+*
+* DESCRIPTION
+* Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_process(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+* This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+* PortInfo Record Receiver, PortInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pir_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_PIR_CTRL_H_
+#define _OSM_PIR_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_portinfo_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/PortInfo Record Receive Controller
+* NAME
+* PortInfo Record Receive Controller
+*
+* DESCRIPTION
+* The PortInfo Record Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The PortInfo Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_t
+* NAME
+* osm_pir_rcv_ctrl_t
+*
+* DESCRIPTION
+* PortInfo Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv_ctrl
+{
+ osm_pir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pir_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the PortInfo Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object
+* PortInfo Record Receiver object
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_construct
+* NAME
+* osm_pir_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a PortInfo Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_construct(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a PortInfo Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pir_rcv_ctrl_init, osm_pir_rcv_ctrl_destroy
+*
+* Calling osm_pir_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_init,
+* osm_pir_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_destroy
+* NAME
+* osm_pir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pir_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_destroy(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* PortInfo Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pir_rcv_ctrl_construct or osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+* osm_pir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_init
+* NAME
+* osm_pir_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pir_rcv_ctrl_init function initializes a
+* PortInfo Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pir_rcv_ctrl_init(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl,
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pir_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfo Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other PortInfo Record Receive Controller methods.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+* osm_pir_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_resp_t.
+ * This object represents an object that responds to SA queries.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SA_RESP_H_
+#define _OSM_SA_RESP_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA Response
+* NAME
+* SA Response
+*
+* DESCRIPTION
+* The SA Response object encapsulates the information
+* needed to respond to an SA query.
+*
+* The SA Response object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: SA Response/osm_sa_resp_t
+* NAME
+* osm_sa_resp_t
+*
+* DESCRIPTION
+* SA Response structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa_resp
+{
+ osm_mad_pool_t *p_pool;
+ osm_log_t *p_log;
+
+} osm_sa_resp_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* SEE ALSO
+* SA Response object
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_construct
+* NAME
+* osm_sa_resp_construct
+*
+* DESCRIPTION
+* This function constructs a SA Response object.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_construct(
+ IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to a SA Response object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sa_resp_init, osm_sa_resp_destroy,
+* and osm_sa_resp_is_inited.
+*
+* Calling osm_sa_resp_construct is a prerequisite to calling any other
+* method except osm_sa_resp_init.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_init,
+* osm_sa_resp_destroy, osm_sa_resp_is_inited
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_destroy
+* NAME
+* osm_sa_resp_destroy
+*
+* DESCRIPTION
+* The osm_sa_resp_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_destroy(
+ IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SA Response object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sa_resp_construct or osm_sa_resp_init.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_init
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_init
+* NAME
+* osm_sa_resp_init
+*
+* DESCRIPTION
+* The osm_sa_resp_init function initializes a
+* SA Response object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_resp_init(
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_sa_resp_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SA Response object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SA Response methods.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_destroy, osm_sa_resp_is_inited
+*********/
+
+/****f* IBA Base: Types/osm_sa_send_error
+* NAME
+* osm_sa_send_error
+*
+* DESCRIPTION
+* Sends a generic SA response with the specified error status.
+* The payload is simply replicated from the request MAD.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_send_error(
+ IN osm_sa_resp_t* const p_resp,
+ IN const osm_madw_t* const p_madw,
+ IN const ib_net16_t sa_status );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_sa_resp_t object.
+*
+* p_madw
+* [in] Original MAD to which the reponse must be sent.
+*
+* sa_status
+* [in] Status to send in the response.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Allows calling other SA Response methods.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_destroy, osm_sa_resp_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_RESP_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SR_H_
+#define _OSM_SR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record Receiver
+* NAME
+* Service Record Receiver
+*
+* DESCRIPTION
+* The Service Record Receiver object encapsulates the information
+* needed to receive the ServiceRecord request from a node.
+*
+* The Service Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy
+*
+*********/
+/****s* OpenSM: Service Record Receiver/osm_sr_rcv_t
+* NAME
+* osm_sr_rcv_t
+*
+* DESCRIPTION
+* Service Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t sr_pool;
+ cl_timer_t sr_timer;
+
+} osm_sr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the osm_sa_resp_t object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* sr_pool
+* Pool of Service Record objects used to generate query reponses.
+*
+* SEE ALSO
+* Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_construct
+* NAME
+* osm_sr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Service Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_construct(
+ IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Service Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sr_rcv_init, osm_sr_rcv_destroy
+*
+* Calling osm_sr_rcv_construct is a prerequisite to calling any other
+* method except osm_sr_rcv_init.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_init, osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_destroy
+* NAME
+* osm_sr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_sr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_destroy(
+ IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Service Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sr_rcv_construct or osm_sr_rcv_init.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_construct,
+* osm_sr_rcv_init
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_init
+* NAME
+* osm_sr_rcv_init
+*
+* DESCRIPTION
+* The osm_sr_rcv_init function initializes a
+* Service Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sr_rcv_init(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Service Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Service Record Receiver methods.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_construct,
+* osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_process
+* NAME
+* osm_sr_rcv_process
+*
+* DESCRIPTION
+* Process the ServiceRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_process(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's ServiceRecord attribute.
+* NOTES
+* This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+* Service Record Receiver
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_lease_cb
+* NAME
+* osm_sr_rcv_lease_cb
+*
+* DESCRIPTION
+* Timer Callback function which is executed to check the lease period
+* expiration
+*
+* SYNOPSIS
+*/
+
+void
+osm_sr_rcv_lease_cb(
+ IN void* context );
+/*
+* PARAMETERS
+* context
+* [in] Pointer to osm_sa_db_t object.
+*
+* NOTES
+* This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+* Service Record Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Service
+ * record attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SRCTRL_H_
+#define _OSM_SRCTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_service_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record Receive Controller
+* NAME
+* Service Record Receive Controller
+*
+* DESCRIPTION
+* The Service Record Receive Controller object encapsulates
+* the information needed to receive the Service Record attribute from a node.
+*
+* The Service Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_t
+* NAME
+* osm_sr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Service Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv_ctrl
+{
+ osm_sr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_sr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Service Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_construct
+* NAME
+* osm_sr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Service Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_construct(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Service Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sr_rcv_ctrl_init, osm_sr_rcv_ctrl_destroy,
+*
+* Calling osm_sr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_psr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_init,
+* osm_sr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_destroy
+* NAME
+* osm_sr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_destroy(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Service Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sr_rcv_ctrl_construct or osm_sr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+* osm_sr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_init
+* NAME
+* osm_sr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_sr_rcv_ctrl_init function initializes a
+* Service Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sr_rcv_ctrl_init(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl,
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the osm_sr_rcv_t Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Service Record Receive Controller methods.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+* osm_sr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SRCTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_slvl_rec_rcv_t.
+ * This object represents the SLtoVL Mapping Table Receiver object.
+ * attribute from a SA query.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_SLVL_REC_RCV_H_
+#define _OSM_SLVL_REC_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SLtoVL Mapping Record Receiver
+* NAME
+* SLtoVL Mapping Record Receiver
+*
+* DESCRIPTION
+* The SLtoVL Mapping Record Receiver object encapsulates the information
+* needed to handle SLtoVL Mapping Record query from a SA.
+*
+* The SLtoVL Mapping Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_t
+* NAME
+* osm_slvl_rec_rcv_t
+*
+* DESCRIPTION
+* SLtoVL Mapping Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_slvl_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable SLtoVL Mapping Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_construct
+* NAME
+* osm_slvl_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a SLtoVL Mapping Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_construct(
+ IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a SLtoVL Mapping Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rec_rcv_init, osm_slvl_rec_rcv_destroy
+*
+* Calling osm_slvl_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_init,
+* osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_destroy
+* NAME
+* osm_slvl_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_destroy(
+ IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SLtoVL Mapping Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rec_rcv_construct or osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+* osm_slvl_rec_rcv_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_init
+* NAME
+* osm_slvl_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_init function initializes a
+* SLtoVL Mapping Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL Mapping Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SLtoVL Mapping Record Receiver methods.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+* osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_process
+* NAME
+* osm_slvl_rec_rcv_process
+*
+* DESCRIPTION
+* Process the SLtoVL Map Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_process(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the SLtoVL Map Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA SLtoVL Map Record attribute.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver, SLtoVL Mapping Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_slvl_rec_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA VL Arbitration
+ * record query from SA client.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_SLVL_REC_CTRL_H_
+#define _OSM_SLVL_REC_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_slvl_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SLtoVL Record Receive Controller
+* NAME
+* SLtoVL Record Receive Controller
+*
+* DESCRIPTION
+* The SLtoVL Mapping Record Receive Controller object encapsulates
+* the information needed to handle SLtoVL Mapping record query from SA client.
+*
+* The SLtoVL Mapping Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_t
+* NAME
+* osm_slvl_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* SLtoVL Mapping Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv_ctrl
+{
+ osm_slvl_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_slvl_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the SLtoVL Mapping Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object
+* SLtoVL Mapping Record Receiver object
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_construct
+* NAME
+* osm_slvl_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SLtoVL Mapping Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_construct(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SLtoVL Mapping Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rec_rcv_ctrl_init, osm_slvl_rec_rcv_ctrl_destroy
+*
+* Calling osm_slvl_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_init,
+* osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_destroy
+* NAME
+* osm_slvl_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_destroy(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SLtoVL Mapping Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rec_rcv_ctrl_construct or osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+* osm_slvl_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_init
+* NAME
+* osm_slvl_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_ctrl_init function initializes a
+* SLtoVL Mapping Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rec_rcv_ctrl_init(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL Mapping Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SLtoVL Mapping Record Receive Controller methods.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+* osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_smir_rcv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SMIR_H_
+#define _OSM_SMIR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receiver
+* NAME
+* Node Info Receiver
+*
+* DESCRIPTION
+* The Node Info Receiver object encapsulates the information
+* needed to receive the NodeRecord attribute from a node.
+*
+* The Node Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receiver/osm_smir_rcv_t
+* NAME
+* osm_smir_rcv_t
+*
+* DESCRIPTION
+* Node Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir
+{
+ osm_subn_t* p_subn;
+ osm_stats_t* p_stats;
+ osm_sa_resp_t* p_resp;
+ osm_mad_pool_t* p_mad_pool;
+ osm_log_t* p_log;
+ cl_plock_t* p_lock;
+
+} osm_smir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* SEE ALSO
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_construct
+* NAME
+* osm_smir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_construct(
+ IN osm_smir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_smir_rcv_init, osm_smir_rcv_destroy
+*
+* Calling osm_smir_rcv_construct is a prerequisite to calling any other
+* method except osm_smir_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_smir_rcv_init, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_destroy
+* NAME
+* osm_smir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_smir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_destroy(
+ IN osm_smir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_smir_rcv_construct or osm_smir_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_smir_rcv_construct,
+* osm_smir_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_init
+* NAME
+* osm_smir_rcv_init
+*
+* DESCRIPTION
+* The osm_smir_rcv_init function initializes a
+* Node Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_rcv_init(
+ IN osm_smir_rcv_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the Statistics object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_smir_rcv_construct, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_process
+* NAME
+* osm_smir_rcv_process
+*
+* DESCRIPTION
+* Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_process(
+ IN osm_smir_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+* This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+* Node Info Receiver, Node Info Response Controller
+*********/
+#if 0
+/*
+ These Component Mask fields comply with IB Spec 1.0.M3
+*/
+#define SMIR_LID_COMPMASK 0x1
+#define SMIR_GUID_COMPMASK 0x4
+#define SMIR_SMKEY_COMPMASK 0x8
+#define SMIR_ACTCOUNT_COMPMASK 0x10
+#define SMIR_PRIORITY_COMPMASK 0x20
+#define SMIR_STATE_COMPMASK 0x40
+#endif
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_smir_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SMIR_CTRL_H_
+#define _OSM_SMIR_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_sminfo_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receive Controller
+* NAME
+* Node Info Receive Controller
+*
+* DESCRIPTION
+* The Node Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_smir_ctrl_t
+* NAME
+* osm_smir_ctrl_t
+*
+* DESCRIPTION
+* Node Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir_ctrl
+{
+ osm_smir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_smir_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Info Receive Controller object
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_smir_ctrl_construct
+* NAME
+* osm_smir_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_construct(
+ IN osm_smir_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_smir_ctrl_init, osm_smir_ctrl_destroy
+*
+* Calling osm_smir_ctrl_construct is a prerequisite to calling any other
+* method except osm_smir_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_smir_ctrl_init,
+* osm_smir_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_smir_ctrl_destroy
+* NAME
+* osm_smir_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_smir_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_destroy(
+ IN osm_smir_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_smir_ctrl_construct or osm_smir_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_smir_ctrl_construct,
+* osm_smir_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_smir_ctrl_init
+* NAME
+* osm_smir_ctrl_init
+*
+* DESCRIPTION
+* The osm_smir_ctrl_init function initializes a
+* Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_ctrl_init(
+ IN osm_smir_ctrl_t* const p_ctrl,
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_smir_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_smir_ctrl_construct,
+* osm_smir_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vlarb_rec_rcv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_VLARB_REC_RCV_H_
+#define _OSM_VLARB_REC_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VLArbitration Record Receiver
+* NAME
+* VLArbitration Record Receiver
+*
+* DESCRIPTION
+* The VLArbitration Record Receiver object encapsulates the information
+* needed to handle VL Arbitration Record query from a SA.
+*
+* The VLArbitration Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_t
+* NAME
+* osm_vlarb_rec_rcv_t
+*
+* DESCRIPTION
+* VLArbitration Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_vlarb_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA reponder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable VLArbitration Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+* osm_vlarb_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a VLArbitration Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_construct(
+ IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a VLArbitration Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vlarb_rec_rcv_init, osm_vlarb_rec_rcv_destroy
+*
+* Calling osm_vlarb_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_init,
+* osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_destroy
+* NAME
+* osm_vlarb_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_destroy(
+ IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* VLArbitration Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vlarb_rec_rcv_construct or osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+* osm_vlarb_rec_rcv_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_init
+* NAME
+* osm_vlarb_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_init function initializes a
+* VLArbitration Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VLArbitration Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VLArbitration Record Receiver methods.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+* osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_process
+* NAME
+* osm_vlarb_rec_rcv_process
+*
+* DESCRIPTION
+* Process the VL Arbitration Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_process(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the VL Arbitration Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA VL Arbitration Record attribute.
+*
+* SEE ALSO
+* VLArbitration Record Receiver, VLArbitration Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_vlarb_rec_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA VL Arbitration
+ * record query from SA client.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_VLARB_REC_CTRL_H_
+#define _OSM_VLARB_REC_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_vlarb_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Vlarbitration Record Receive Controller
+* NAME
+* Vlarbitration Record Receive Controller
+*
+* DESCRIPTION
+* The VLArbitration Record Receive Controller object encapsulates
+* the information needed to handle VLArbitration record query from SA client.
+*
+* The VLArbitration Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_t
+* NAME
+* osm_vlarb_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* VLArbitration Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv_ctrl
+{
+ osm_vlarb_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_vlarb_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the VLArbitration Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object
+* VLArbitration Record Receiver object
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_construct
+* NAME
+* osm_vlarb_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a VLArbitration Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_construct(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a VLArbitration Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vlarb_rec_rcv_ctrl_init, osm_vlarb_rec_rcv_ctrl_destroy
+*
+* Calling osm_vlarb_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_init,
+* osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_destroy
+* NAME
+* osm_vlarb_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_destroy(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* VLArbitration Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vlarb_rec_rcv_ctrl_construct or osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+* osm_vlarb_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_init
+* NAME
+* osm_vlarb_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_ctrl_init function initializes a
+* VLArbitration Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vlarb_rec_rcv_ctrl_init(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vlarb_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VLArbitration Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VLArbitration Record Receive Controller methods.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+* osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_SVCR_H_
+#define _OSM_SVCR_H_
+
+
+/*
+ * Abstract:
+ * Declaration of osm_service_rec_t.
+ * This object represents an IBA Service Record.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record
+* NAME
+* Service Record
+*
+* DESCRIPTION
+* The service record encapsulates the information needed by the
+* SA to manage service registrations.
+*
+* The service records is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Service Record/osm_svcr_t
+* NAME
+* osm_svcr_t
+*
+* DESCRIPTION
+* Service Record structure.
+*
+* The osm_svcr_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _osm_svcr_t
+{
+ cl_list_item_t list_item;
+ ib_net64_t svc_id;
+ ib_service_record_t service_record;
+ uint32_t modified_time;
+ uint32_t lease_period;
+
+} osm_svcr_t;
+/*
+* FIELDS
+* map_item
+* Map Item for qmap linkage. Must be first element!!
+*
+* svc_rec
+* IB Service record structure
+*
+* modified_time
+* Last modified time of this record in milliseconds
+*
+* lease_period
+* Remaining lease period for this record
+*
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Service Record/osm_svcr_new
+* NAME
+* osm_svcr_new
+*
+* DESCRIPTION
+* Allocates and initializes a Service Record for use.
+*
+* SYNOPSIS
+*/
+osm_svcr_t*
+osm_svcr_new(
+ IN const ib_service_record_t *p_svc_rec );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to IB Service Record
+*
+* RETURN VALUES
+* pointer to osm_svcr_t structure.
+*
+* NOTES
+* Allows calling other service record methods.
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+
+/****f* OpenSM: Service Record/osm_svcr_init
+* NAME
+* osm_svcr_new
+*
+* DESCRIPTION
+* Initializes the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_init(
+ IN osm_svcr_t* const p_svcr,
+ IN const ib_service_record_t *p_svc_rec );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to osm_svcr_t structure
+* p_svc_rec
+* [in] Pointer to the ib_service_record_t
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_construct
+* NAME
+* osm_svcr_construct
+*
+* DESCRIPTION
+* Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_construct(
+ IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_destroy
+* NAME
+* osm_svcr_destroy
+*
+* DESCRIPTION
+* Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_destroy(
+ IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+
+
+osm_svcr_t*
+osm_svcr_get_by_rid(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN ib_service_record_t* const p_svc_rec );
+
+void
+osm_svcr_insert_to_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_svcr_t *p_svcr);
+void
+osm_svcr_remove_from_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_svcr_t *p_svcr);
+
+
+END_C_DECLS
+
+#endif /* _OSM_SVCR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Map Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_SLVL_RCV_H_
+#define _OSM_SLVL_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Slvl Map Receiver
+* NAME
+* Slvl Map Receiver
+*
+* DESCRIPTION
+* The Slvl Map Receiver object encapsulates the information
+* needed to set or get the SLtoVL map attribute from a port.
+*
+* The Slvl Map Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: Slvl Map Receiver/osm_slvl_rcv_t
+* NAME
+* osm_slvl_rcv_t
+*
+* DESCRIPTION
+* Slvl Map Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_slvl_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_construct
+* NAME
+* osm_slvl_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Slvl Map Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_construct(
+ IN osm_slvl_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Slvl Map Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rcv_destroy
+*
+* Calling osm_slvl_rcv_construct is a prerequisite to calling any other
+* method except osm_slvl_rcv_init.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_init,
+* osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_destroy
+* NAME
+* osm_slvl_rcv_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_destroy(
+ IN osm_slvl_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Slvl Map Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rcv_construct or osm_slvl_rcv_init.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_construct,
+* osm_slvl_rcv_init
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_init
+* NAME
+* osm_slvl_rcv_init
+*
+* DESCRIPTION
+* The osm_slvl_rcv_init function initializes a
+* Slvl Map Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_init(
+ IN osm_slvl_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Slvl Map Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Slvl Map Receiver methods.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_construct,
+* osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_process
+* NAME
+* osm_slvl_rcv_process
+*
+* DESCRIPTION
+* Process the SLtoVL map attribute.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_process(
+ IN const osm_slvl_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* Slvl Map Receiver, Slvl Map Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_SLVL_RCV_CTRL_H_
+#define _OSM_SLVL_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_slvl_map_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SltoVL Map Table Receive Controller
+* NAME
+* Slvl Map Receive Controller
+*
+* DESCRIPTION
+* The Slvl Map Receive Controller object encapsulates
+* the information needed to get or set SLtoVL Map of a port.
+*
+* The Slvl Map Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_t
+* NAME
+* osm_slvl_rcv_ctrl_t
+*
+* DESCRIPTION
+* Slvl Map Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv_ctrl
+{
+ osm_slvl_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_slvl_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Slvl Map Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object
+* Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_construct
+* NAME
+* osm_slvl_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Slvl Map Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_construct(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Slvl Map Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rcv_ctrl_init, osm_slvl_rcv_ctrl_destroy,
+* and osm_slvl_rcv_ctrl_is_inited.
+*
+* Calling osm_slvl_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_init,
+* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_destroy
+* NAME
+* osm_slvl_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_destroy(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Slvl Map Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_init
+* NAME
+* osm_slvl_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_slvl_rcv_ctrl_init function initializes a
+* Slvl Map Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_ctrl_init(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_slvl_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Slvl Map Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Slvl Map Receive Controller methods.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_is_inited
+* NAME
+* osm_slvl_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_slvl_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_slvl_rcv_ctrl_is_inited(
+ IN const osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_t, osm_other_sm_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_SM_H_
+#define _OSM_SM_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_stats.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_db.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM
+* NAME
+* SM
+*
+* DESCRIPTION
+* The SM object encapsulates the information needed by the
+* OpenSM to instantiate a subnet manager. The OpenSM allocates
+* one SM object per subnet manager.
+*
+* The SM object is thread safe.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SM/osm_sm_t
+* NAME
+* osm_sm_t
+*
+* DESCRIPTION
+* Subnet Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm
+{
+ osm_thread_state_t thread_state;
+ cl_event_t signal;
+ cl_event_t subnet_up_event;
+ cl_thread_t sweeper;
+ osm_subn_t *p_subn;
+ osm_db_t *p_db;
+ osm_vendor_t *p_vendor;
+ osm_log_t *p_log;
+ osm_mad_pool_t *p_mad_pool;
+ osm_vl15_t *p_vl15;
+ cl_dispatcher_t *p_disp;
+ cl_plock_t *p_lock;
+ atomic32_t sm_trans_id;
+ osm_req_t req;
+ osm_req_ctrl_t req_ctrl;
+ osm_resp_t resp;
+ osm_ni_rcv_t ni_rcv;
+ osm_ni_rcv_ctrl_t ni_rcv_ctrl;
+ osm_pi_rcv_t pi_rcv;
+ osm_pi_rcv_ctrl_t pi_rcv_ctrl;
+ osm_nd_rcv_t nd_rcv;
+ osm_nd_rcv_ctrl_t nd_rcv_ctrl;
+ osm_sm_mad_ctrl_t mad_ctrl;
+ osm_si_rcv_t si_rcv;
+ osm_si_rcv_ctrl_t si_rcv_ctrl;
+ osm_state_mgr_ctrl_t state_mgr_ctrl;
+ osm_lid_mgr_t lid_mgr;
+ osm_ucast_mgr_t ucast_mgr;
+ osm_link_mgr_t link_mgr;
+ osm_state_mgr_t state_mgr;
+ osm_drop_mgr_t drop_mgr;
+ osm_lft_rcv_t lft_rcv;
+ osm_lft_rcv_ctrl_t lft_rcv_ctrl;
+ osm_mft_rcv_t mft_rcv;
+ osm_mft_rcv_ctrl_t mft_rcv_ctrl;
+ osm_sweep_fail_ctrl_t sweep_fail_ctrl;
+ osm_sminfo_rcv_t sm_info_rcv;
+ osm_sminfo_rcv_ctrl_t sm_info_rcv_ctrl;
+ osm_trap_rcv_t trap_rcv;
+ osm_trap_rcv_ctrl_t trap_rcv_ctrl;
+ osm_sm_state_mgr_t sm_state_mgr;
+ osm_mcast_mgr_t mcast_mgr;
+ osm_slvl_rcv_t slvl_rcv;
+ osm_slvl_rcv_ctrl_t slvl_rcv_ctrl;
+ osm_vla_rcv_t vla_rcv;
+ osm_vla_rcv_ctrl_t vla_rcv_ctrl;
+ osm_pkey_rcv_t pkey_rcv;
+ osm_pkey_rcv_ctrl_t pkey_rcv_ctrl;
+ char* p_report_buf;
+
+} osm_sm_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_db
+* Pointer to the database (persistency) object
+*
+* p_vendor
+* Pointer to the vendor specific interfaces object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mad_pool
+* Pointer to the MAD pool.
+*
+* p_vl15
+* Pointer to the VL15 interface.
+*
+* req
+* Generic MAD attribute requester.
+*
+* req_ctrl
+* Controller for the generic requester.
+*
+* resp
+* MAD attribute responder.
+*
+* nd_rcv_ctrl
+* Node Description Receive Controller.
+*
+* ni_rcv_ctrl
+* Node Info Receive Controller.
+*
+* pi_rcv_ctrl
+* Port Info Receive Controller.
+*
+* si_rcv_ctrl
+* Switch Info Receive Controller.
+*
+* nd_rcv_ctrl
+* Node Description Receive Controller.
+*
+* mad_ctrl
+* MAD Controller.
+*
+* smi_get_ctrl
+* SM Info Get Controller.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_construct
+* NAME
+* osm_sm_construct
+*
+* DESCRIPTION
+* This function constructs an SM object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_construct(
+ IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to a SM object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sm_init, osm_sm_destroy
+*
+* Calling osm_sm_construct is a prerequisite to calling any other
+* method except osm_sm_init.
+*
+* SEE ALSO
+* SM object, osm_sm_init, osm_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_sm_shutdown
+* NAME
+* osm_sm_shutdown
+*
+* DESCRIPTION
+* The osm_sm_shutdown function shutdowns an SM, stopping the sweeper
+* and unregistering all messages from the dispatcher
+*
+* SYNOPSIS
+*/
+void
+osm_sm_shutdown(
+ IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to a SM object to shutdown.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* SEE ALSO
+* SM object, osm_sm_construct, osm_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_sm_destroy
+* NAME
+* osm_sm_destroy
+*
+* DESCRIPTION
+* The osm_sm_destroy function destroys an SM, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_destroy(
+ IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to a SM object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified SM object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_sm_construct or
+* osm_sm_init.
+*
+* SEE ALSO
+* SM object, osm_sm_construct, osm_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_sm_init
+* NAME
+* osm_sm_init
+*
+* DESCRIPTION
+* The osm_sm_init function initializes a SM object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_init(
+ IN osm_sm_t* const p_sm,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_vendor
+* [in] Pointer to the vendor specific interfaces object.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_stats
+* [in] Pointer to the statistics object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SM object was initialized successfully.
+*
+* NOTES
+* Allows calling other SM methods.
+*
+* SEE ALSO
+* SM object, osm_sm_construct, osm_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_sm_sweep
+* NAME
+* osm_sm_sweep
+*
+* DESCRIPTION
+* Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_sweep(
+ IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the sweep completed successfully.
+*
+* NOTES
+*
+* SEE ALSO
+* SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_bind
+* NAME
+* osm_sm_bind
+*
+* DESCRIPTION
+* Binds the sm object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_bind(
+ IN osm_sm_t* const p_sm,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object to bind.
+*
+* port_guid
+* [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given SM object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mcgrp_join
+* NAME
+* osm_sm_mcgrp_join
+*
+* DESCRIPTION
+* Adds a port to the multicast group. Creates the multicast group
+* if necessary.
+*
+* This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_join(
+ IN osm_sm_t* const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object.
+*
+* mlid
+* [in] Multicast LID
+*
+* port_guid
+* [in] Port GUID to add to the group.
+*
+* req_type
+* [in] Type of the MC request that caused this join
+* (MC create/join).
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mcgrp_leave
+* NAME
+* osm_sm_mcgrp_leave
+*
+* DESCRIPTION
+* Removes a port from the multicast group.
+*
+* This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+ IN osm_sm_t* const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object.
+*
+* mlid
+* [in] Multicast LID
+*
+* port_guid
+* [in] Port GUID to remove from the group.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_wait_for_subnet_up
+* NAME
+* osm_opensm_wait_for_subnet_up
+*
+* DESCRIPTION
+* Blocks the calling thread until the subnet is up.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_sm_wait_for_subnet_up(
+ IN osm_sm_t* const p_sm,
+ IN uint32_t const wait_us,
+ IN boolean_t const interruptible )
+{
+ return( cl_event_wait_on( &p_sm->subnet_up_event,
+ wait_us, interruptible ) );
+}
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* wait_us
+* [in] Number of microseconds to wait.
+*
+* interruptible
+* [in] Indicates whether the wait operation can be interrupted
+* by external signals.
+*
+* RETURN VALUES
+* CL_SUCCESS if the wait operation succeeded in response to the event
+* being set.
+*
+* CL_TIMEOUT if the specified time period elapses.
+*
+* CL_NOT_DONE if the wait was interrupted by an external signal.
+*
+* CL_ERROR if the wait operation failed.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_smi_get_ctrl_t.
+ * This object represents a controller that receives the IBA SMInfo
+ * query from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SM_INFO_GET_CTRL_H_
+#define _OSM_SM_INFO_GET_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM Info Get Controller
+* NAME
+* SM Info Get Controller
+*
+* DESCRIPTION
+* The SM Info Get Controller object encapsulates the information
+* needed to handle the SwitchInfo query from a node.
+*
+* The SM Info Get Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_t
+* NAME
+* osm_smi_get_ctrl_t
+*
+* DESCRIPTION
+* SM Info Get Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smi_get_ctrl
+{
+ osm_sminfo_t *p_smi;
+ osm_mad_pool_t *p_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_smi_get_ctrl_t;
+/*
+* FIELDS
+* p_smi
+* Pointer to the SM Info object of the SM.
+*
+* p_pool
+* Pointer to the MAD pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* SM Info Get Controller object
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_construct
+* NAME
+* osm_smi_get_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SM Info Get Controller object.
+*
+* SYNOPSIS
+*/
+void osm_smi_get_ctrl_construct(
+ IN osm_smi_get_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SM Info Get Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_smi_get_ctrl_init, osm_smi_get_ctrl_destroy,
+* and osm_smi_get_ctrl_is_inited.
+*
+* Calling osm_smi_get_ctrl_construct is a prerequisite to calling any other
+* method except osm_smi_get_ctrl_init.
+*
+* SEE ALSO
+* SM Info Get Controller object, osm_smi_get_ctrl_init,
+* osm_smi_get_ctrl_destroy, osm_smi_get_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_destroy
+* NAME
+* osm_smi_get_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_smi_get_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_smi_get_ctrl_destroy(
+ IN osm_smi_get_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SM Info Get Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_smi_get_ctrl_construct or osm_smi_get_ctrl_init.
+*
+* SEE ALSO
+* SM Info Get Controller object, osm_smi_get_ctrl_construct,
+* osm_smi_get_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_init
+* NAME
+* osm_smi_get_ctrl_init
+*
+* DESCRIPTION
+* The osm_smi_get_ctrl_init function initializes a
+* SM Info Get Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smi_get_ctrl_init(
+ IN osm_smi_get_ctrl_t* const p_ctrl,
+ IN osm_sminfo_t* const p_smi,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smi_get_ctrl_t object to initialize.
+*
+* p_smi
+* [in] Pointer to the SMInfo object of the SM.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SM Info Get Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM Info Get Controller methods.
+*
+* SEE ALSO
+* SM Info Get Controller object, osm_smi_get_ctrl_construct,
+* osm_smi_get_ctrl_destroy, osm_smi_get_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_is_inited
+* NAME
+* osm_smi_get_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_smi_get_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_smi_get_ctrl_is_inited(
+ IN const osm_smi_get_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smi_get_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_smi_get_ctrl_construct or osm_smi_get_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* SM Info Get Controller object, osm_smi_get_ctrl_construct,
+* osm_smi_get_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_process
+* NAME
+* osm_smi_get_ctrl_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smi_get_ctrl_process(
+ IN const osm_smi_get_ctrl_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smi_get_ctrl_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* SM Info Get Controller, SM Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_INFO_GET_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_mad_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SM_MAD_CTRL_H_
+#define _OSM_SM_MAD_CTRL_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl15intf.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM MAD Controller
+* NAME
+* SM MAD Controller
+*
+* DESCRIPTION
+* The SM MAD Controller object encapsulates
+* the information needed to receive MADs from the transport layer.
+*
+* The SM MAD Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_t
+* NAME
+* osm_sm_mad_ctrl_t
+*
+* DESCRIPTION
+* SM MAD Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm_mad_ctrl
+{
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+ osm_mad_pool_t *p_mad_pool;
+ osm_vl15_t *p_vl15;
+ osm_vendor_t *p_vendor;
+ osm_bind_handle_t h_bind;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+ osm_stats_t *p_stats;
+
+} osm_sm_mad_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_subn
+* Pointer to the subnet object.
+*
+* p_mad_pool
+* Pointer to the MAD pool.
+*
+* p_vendor
+* Pointer to the vendor specific interfaces object.
+*
+* h_bind
+* Bind handle returned by the transport layer.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* SEE ALSO
+* SM MAD Controller object
+* SM MADr object
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_construct
+* NAME
+* osm_sm_mad_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SM MAD Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_mad_ctrl_construct(
+ IN osm_sm_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SM MAD Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sm_mad_ctrl_init, osm_sm_mad_ctrl_destroy,
+* and osm_sm_mad_ctrl_is_inited.
+*
+* Calling osm_sm_mad_ctrl_construct is a prerequisite to calling any other
+* method except osm_sm_mad_ctrl_init.
+*
+* SEE ALSO
+* SM MAD Controller object, osm_sm_mad_ctrl_init,
+* osm_sm_mad_ctrl_destroy, osm_sm_mad_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_destroy
+* NAME
+* osm_sm_mad_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sm_mad_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_mad_ctrl_destroy(
+ IN osm_sm_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SM MAD Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sm_mad_ctrl_construct or osm_sm_mad_ctrl_init.
+*
+* SEE ALSO
+* SM MAD Controller object, osm_sm_mad_ctrl_construct,
+* osm_sm_mad_ctrl_init
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_init
+* NAME
+* osm_sm_mad_ctrl_init
+*
+* DESCRIPTION
+* The osm_sm_mad_ctrl_init function initializes a
+* SM MAD Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mad_ctrl_init(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sm_mad_ctrl_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface object.
+*
+* p_vendor
+* [in] Pointer to the vendor specific interfaces object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_stats
+* [in] Pointer to the OpenSM stastics block.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SM MAD Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM MAD Controller methods.
+*
+* SEE ALSO
+* SM MAD Controller object, osm_sm_mad_ctrl_construct,
+* osm_sm_mad_ctrl_destroy, osm_sm_mad_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM/osm_sm_mad_ctrl_bind
+* NAME
+* osm_sm_mad_ctrl_bind
+*
+* DESCRIPTION
+* Binds the SM MAD Controller object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mad_ctrl_bind(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sm_mad_ctrl_t object to initialize.
+*
+* port_guid
+* [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* A given SM MAD Controller object can only be bound to one
+* port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mad_ctrl_get_bind_handle
+* NAME
+* osm_sm_mad_ctrl_get_bind_handle
+*
+* DESCRIPTION
+* Returns the bind handle.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_sm_mad_ctrl_get_bind_handle(
+ IN const osm_sm_mad_ctrl_t* const p_ctrl )
+{
+ return( p_ctrl->h_bind );
+}
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sm_mad_ctrl_t object.
+*
+* RETURN VALUES
+* Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE
+* if no port has been bound.
+*
+* NOTES
+* A given SM MAD Controller object can only be bound to one
+* port at a time.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_MAD_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_state_mgr_t.
+ * This object represents the SM State Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+#ifndef _OSM_SM_STATE_MGR_H_
+#define _OSM_SM_STATE_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_remote_sm.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM State Manager
+* NAME
+* SM State Manager
+*
+* DESCRIPTION
+* The SM State Manager object encapsulates the information
+* needed to control the state of the SM.
+*
+* The SM State Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: SM State Manager/osm_sm_state_mgr_t
+* NAME
+* osm_sm_state_mgr_t
+*
+* DESCRIPTION
+* SM State Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm_state_mgr
+{
+ cl_spinlock_t state_lock;
+ cl_timer_t polling_timer;
+ uint32_t retry_number;
+ ib_net64_t master_guid;
+ osm_state_mgr_t* p_state_mgr;
+ osm_subn_t* p_subn;
+ osm_req_t* p_req;
+ osm_log_t* p_log;
+ osm_remote_sm_t* p_polling_sm;
+} osm_sm_state_mgr_t;
+
+/*
+* FIELDS
+* state_lock
+* Spinlock gaurding the state and processes.
+*
+* retry_number
+* Used on Standby state - to count the number of retries of queries to the master SM.
+*
+* polling_timer
+* Timer for polling
+*
+* p_state_mgr
+* Point to the state manager object
+*
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_polling_sm
+* Pointer to a osm_remote_sm_t object. When our SM needs to poll on a remote
+* sm, this will be the pointer of the polled SM.
+*
+* SEE ALSO
+* SM State Manager object
+*********/
+
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_construct
+* NAME
+* osm_sm_state_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a SM State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_construct(
+ IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to a SM State Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_sm_state_mgr_destroy
+*
+* Calling osm_sm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_sm_state_mgr_init.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_init,
+* osm_sm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_destroy
+* NAME
+* osm_sm_state_mgr_destroy
+*
+* DESCRIPTION
+* The osm_sm_state_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_destroy(
+ IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SM State Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sm_state_mgr_construct or osm_sm_state_mgr_init.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_construct,
+* osm_sm_state_mgr_init
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_init
+* NAME
+* osm_sm_state_mgr_init
+*
+* DESCRIPTION
+* The osm_sm_state_mgr_init function initializes a
+* SM State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_init(
+ IN osm_sm_state_mgr_t* const p_sm_mgr,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object to initialize.
+*
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SM State Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM State Manager methods.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_construct,
+* osm_sm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_process
+* NAME
+* osm_sm_state_mgr_process
+*
+* DESCRIPTION
+* Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_process(
+ IN osm_sm_state_mgr_t* const p_sm_mgr,
+ IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object.
+*
+* signal
+* [in] Signal to the state SM engine.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_signal_master_is_alive
+* NAME
+* osm_sm_state_mgr_signal_master_is_alive
+*
+* DESCRIPTION
+* Signals that the remote Master SM is alive.
+* Need to clear the retry_number variable.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_signal_master_is_alive(
+ IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_check_legality
+* NAME
+* osm_sm_state_mgr_check_legality
+*
+* DESCRIPTION
+* Checks the legality of the signal received, according to the
+* current state of the SM state machine.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_check_legality(
+ IN osm_sm_state_mgr_t* const p_sm_mgr,
+ IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object.
+*
+* signal
+* [in] Signal to the state SM engine.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_STATE_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SMINFO_RCV_H_
+#define _OSM_SMINFO_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SMInfo Receiver
+* NAME
+* SMInfo Receiver
+*
+* DESCRIPTION
+* The SMInfo Receiver object encapsulates the information
+* needed to receive the SMInfo attribute from a node.
+*
+* The SMInfo Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: SMInfo Receiver/osm_sminfo_rcv_t
+* NAME
+* osm_sminfo_rcv_t
+*
+* DESCRIPTION
+* SMInfo Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv
+{
+ osm_subn_t *p_subn;
+ osm_stats_t *p_stats;
+ osm_log_t *p_log;
+ osm_resp_t *p_resp;
+ osm_state_mgr_t *p_state_mgr;
+ struct _osm_sm_state_mgr *p_sm_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_sminfo_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_resp
+* Pointer to the generic MAD responder object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_sm_state_mgr
+* Pointer to the SM State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* SMInfo Receiver object
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_construct
+* NAME
+* osm_sminfo_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a SMInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_construct(
+ IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a SMInfo Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sminfo_rcv_init, osm_sminfo_rcv_destroy
+*
+* Calling osm_sminfo_rcv_construct is a prerequisite to calling any other
+* method except osm_sminfo_rcv_init.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_init,
+* osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_destroy
+* NAME
+* osm_sminfo_rcv_destroy
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_destroy(
+ IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SMInfo Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sminfo_rcv_construct or osm_sminfo_rcv_init.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_construct,
+* osm_sminfo_rcv_init
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_init
+* NAME
+* osm_sminfo_rcv_init
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_init function initializes a
+* SMInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sminfo_rcv_init(
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN struct _osm_sm_state_mgr* const p_sm_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_resp
+* [in] Pointer to the generic MAD Responder object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_sm_state_mgr
+* [in] Pointer to the SM State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SMInfo Receiver methods.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_construct,
+* osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_process
+* NAME
+* osm_sminfo_rcv_process
+*
+* DESCRIPTION
+* Process the SMInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_process(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SMInfo attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo processing was successful.
+*
+* NOTES
+* This function processes a SMInfo attribute.
+*
+* SEE ALSO
+* SMInfo Receiver, SMInfo Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMINFO_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sminfo_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA SMInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMINFO_RCV_CTRL_H_
+#define _OSM_SMINFO_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SMInfo Receive Controller
+* NAME
+* SMInfo Receive Controller
+*
+* DESCRIPTION
+* The SMInfo Receive Controller object encapsulates the information
+* needed to receive the SMInfo attribute from a node.
+*
+* The SMInfo Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_t
+* NAME
+* osm_sminfo_rcv_ctrl_t
+*
+* DESCRIPTION
+* SMInfo Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv_ctrl
+{
+ osm_sminfo_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_sminfo_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the SMInfo Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* SMInfo Receive Controller object
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_construct
+* NAME
+* osm_sminfo_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SMInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_construct(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SMInfo Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sminfo_rcv_ctrl_init, osm_sminfo_rcv_ctrl_destroy
+*
+* Calling osm_sminfo_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_init,
+* osm_sminfo_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_destroy
+* NAME
+* osm_sminfo_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_destroy(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SMInfo Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sminfo_rcv_ctrl_construct or osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+* osm_sminfo_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_init
+* NAME
+* osm_sminfo_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_ctrl_init function initializes a
+* SMInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sminfo_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SMInfo Receive Controller methods.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+* osm_sminfo_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_SMINFO_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_state_mgr_t.
+ * This object represents the State Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_STATE_MGR_H_
+#define _OSM_STATE_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/State Manager
+* NAME
+* State Manager
+*
+* DESCRIPTION
+* The State Manager object encapsulates the information
+* needed to control subnet sweeps and configuration.
+*
+* The State Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: State Manager/osm_state_mgr_t
+* NAME
+* osm_state_mgr_t
+*
+* DESCRIPTION
+* State Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_lid_mgr_t *p_lid_mgr;
+ osm_ucast_mgr_t *p_ucast_mgr;
+ osm_mcast_mgr_t *p_mcast_mgr;
+ osm_link_mgr_t *p_link_mgr;
+ osm_drop_mgr_t *p_drop_mgr;
+ osm_req_t *p_req;
+ osm_stats_t *p_stats;
+ struct _osm_sm_state_mgr *p_sm_state_mgr;
+ const osm_sm_mad_ctrl_t *p_mad_ctrl;
+ cl_spinlock_t state_lock;
+ cl_spinlock_t idle_lock;
+ cl_qlist_t idle_time_list;
+ cl_plock_t *p_lock;
+ cl_event_t *p_subnet_up_event;
+ char *p_report_buf;
+ osm_sm_state_t state;
+ osm_state_mgr_mode_t state_step_mode;
+ osm_signal_t next_stage_signal;
+} osm_state_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lid_mgr
+* Pointer to the LID Manager object.
+*
+* p_ucast_mgr
+* Pointer to the Unicast Manager object.
+*
+* p_mcast_mgr
+* Pointer to the Multicast Manager object.
+*
+* p_link_mgr
+* Pointer to the Link Manager object.
+*
+* p_drop_mgr
+* Pointer to the Drop Manager object.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_sm_state_mgr
+* Pointer to the SM state mgr object.
+*
+* p_mad_ctrl
+* Pointer to the SM's MAD Controller object.
+*
+* state_lock
+* Spinlock gaurding the state and processes.
+*
+* p_lock
+* lock guarding the subnet object.
+*
+* p_subnet_up_event
+* Pointer to the event to set if/when the subnet comes up.
+*
+* p_report_buf
+* Pointer to the large log buffer used for user reports.
+*
+* state
+* State of the SM.
+*
+* state_step_mode
+* Controls the mode of progressing to next stage:
+* OSM_STATE_STEP_CONTINUOUS - normal automatic progress mode
+* OSM_STATE_STEP_TAKE_ONE - do one step and stop
+* OSM_STATE_STEP_BREAK - stop before taking next step
+*
+* next_stage_signal
+* Stores the signal to be provided when running the next stage.
+*
+* SEE ALSO
+* State Manager object
+*********/
+
+/****s* OpenSM: State Manager/_osm_idle_item
+* NAME
+* _osm_idle_item
+*
+* DESCRIPTION
+* Idle item.
+*
+* SYNOPSIS
+*/
+
+typedef osm_signal_t
+(*osm_pfn_start_t)(
+ IN void *context1,
+ IN void *context2 );
+
+typedef void
+(*osm_pfn_done_t)(
+ IN void *context1,
+ IN void *context2 );
+
+typedef struct _osm_idle_item
+{
+ cl_list_item_t list_item;
+ void* context1;
+ void* context2;
+ osm_pfn_start_t pfn_start;
+ osm_pfn_done_t pfn_done;
+}osm_idle_item_t;
+
+/*
+* FIELDS
+* list_item
+* list item.
+*
+* context1
+* Context pointer
+*
+* context2
+* Context pointer
+*
+* pfn_start
+* Pointer to the start function.
+*
+* pfn_done
+* Pointer to the dine function.
+* SEE ALSO
+* State Manager object
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_process_idle
+* NAME
+* osm_state_mgr_process_idle
+*
+* DESCRIPTION
+* Formulates the osm_idle_item and inserts it into the queue and
+* signals the state manager.
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_state_mgr_process_idle(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_pfn_start_t pfn_start,
+ IN osm_pfn_done_t pfn_done,
+ void* context1,
+ void* context2
+ );
+
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a State Manager object to construct.
+*
+* pfn_start
+* [in] Pointer the start function which will be called at
+* idle time.
+*
+* pfn_done
+* [in] pointer the done function which will be called
+* when outstanding smps is zero
+*
+* context1
+* [in] Pointer to void
+*
+* context2
+* [in] Pointer to void
+*
+* RETURN VALUE
+* IB_SUCCESS or IB_ERROR
+*
+* NOTES
+* Allows osm_state_mgr_destroy
+*
+* Calling osm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_init,
+* osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_construct
+* NAME
+* osm_state_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_construct(
+ IN osm_state_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a State Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_state_mgr_destroy
+*
+* Calling osm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_init,
+* osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_destroy
+* NAME
+* osm_state_mgr_destroy
+*
+* DESCRIPTION
+* The osm_state_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_destroy(
+ IN osm_state_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* State Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_state_mgr_construct or osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_construct,
+* osm_state_mgr_init
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_init
+* NAME
+* osm_state_mgr_init
+*
+* DESCRIPTION
+* The osm_state_mgr_init function initializes a
+* State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_init(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_lid_mgr_t* const p_lid_mgr,
+ IN osm_ucast_mgr_t* const p_ucast_mgr,
+ IN osm_mcast_mgr_t* const p_mcast_mgr,
+ IN osm_link_mgr_t* const p_link_mgr,
+ IN osm_drop_mgr_t* const p_drop_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_stats_t* const p_stats,
+ IN struct _osm_sm_state_mgr* const p_sm_state_mgr,
+ IN const osm_sm_mad_ctrl_t* const p_mad_ctrl,
+ IN cl_plock_t* const p_lock,
+ IN cl_event_t* const p_subnet_up_event,
+ IN char* const p_report_buf,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_lid_mgr
+* [in] Pointer to the LID Manager object.
+*
+* p_ucast_mgr
+* [in] Pointer to the Unicast Manager object.
+*
+* p_mcast_mgr
+* [in] Pointer to the Multicast Manager object.
+*
+* p_link_mgr
+* [in] Pointer to the Link Manager object.
+*
+* p_drop_mgr
+* [in] Pointer to the Drop Manager object.
+*
+* p_req
+* [in] Pointer to the Request Controller object.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_sm_state_mgr
+* [in] Pointer to the SM state mgr object.
+*
+* p_mad_ctrl
+* [in] Pointer to the SM's mad controller.
+*
+* p_subnet_up_event
+* [in] Pointer to the event to set if/when the subnet comes up.
+*
+* p_report_buf
+* [in] Pointer to the large log buffer used for user reports.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the State Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other State Manager methods.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_construct,
+* osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_sm_is_greater_than
+* NAME
+* osm_sm_is_greater_than
+*
+* DESCRIPTION
+* Compares two SM's (14.4.1.2)
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_sm_is_greater_than (
+ IN const uint8_t l_priority,
+ IN const ib_net64_t l_guid,
+ IN const uint8_t r_priority,
+ IN const ib_net64_t r_guid )
+{
+ if( l_priority > r_priority )
+ {
+ return( TRUE );
+ }
+ else
+ {
+ if( l_priority == r_priority )
+ {
+ if( cl_ntoh64(l_guid) < cl_ntoh64(r_guid) )
+ {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+/*
+* PARAMETERS
+* l_priority
+* [in] Priority of the SM on the "left"
+*
+* l_guid
+* [in] GUID of the SM on the "left"
+*
+* r_priority
+* [in] Priority of the SM on the "right"
+*
+* r_guid
+* [in] GUID of the SM on the "right"
+*
+* RETURN VALUES
+* Return TRUE if an sm with l_priority and l_guid is higher than an sm
+* with r_priority and r_guid,
+* return FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_process
+* NAME
+* osm_state_mgr_process
+*
+* DESCRIPTION
+* Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_process(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_signal_t signal );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object.
+*
+* signal
+* [in] Signal to the state engine.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_STATE_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_state_mgr_ctrl_t.
+ * This object represents a controller that receives the
+ * State indication after a subnet sweep.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATE_MGR_CTRL_H_
+#define _OSM_STATE_MGR_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/State Manager Controller
+* NAME
+* State Manager Controller
+*
+* DESCRIPTION
+* The State Manager Controller object encapsulates the information
+* needed to pass the dispatcher message from the dispatcher
+* to the State Manager.
+*
+* The State Manager Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: State Manager Controller/osm_state_mgr_ctrl_t
+* NAME
+* osm_state_mgr_ctrl_t
+*
+* DESCRIPTION
+* State Manager Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr_ctrl
+{
+ osm_state_mgr_t *p_mgr;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_state_mgr_ctrl_t;
+/*
+* FIELDS
+* p_mgr
+* Pointer to the State Manager object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* State Manager Controller object
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_construct
+* NAME
+* osm_state_mgr_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a State Manager Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_construct(
+ IN osm_state_mgr_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a State Manager Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_state_mgr_ctrl_init, osm_state_mgr_ctrl_destroy,
+* and osm_state_mgr_ctrl_is_inited.
+*
+* Calling osm_state_mgr_ctrl_construct is a prerequisite to calling any other
+* method except osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_init,
+* osm_state_mgr_ctrl_destroy
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_destroy
+* NAME
+* osm_state_mgr_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_state_mgr_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_destroy(
+ IN osm_state_mgr_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* State Manager Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_state_mgr_ctrl_construct or osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_construct,
+* osm_state_mgr_ctrl_init
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_init
+* NAME
+* osm_state_mgr_ctrl_init
+*
+* DESCRIPTION
+* The osm_state_mgr_ctrl_init function initializes a
+* State Manager Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+ IN osm_state_mgr_ctrl_t* const p_ctrl,
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_state_mgr_ctrl_t object to initialize.
+*
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the State Manager Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other State Manager Controller methods.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_construct,
+* osm_state_mgr_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_STATE_MGR_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_stats_t.
+ * This object represents the OpenSM statistics object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATS_H_
+#define _OSM_STATS_H_
+
+#include <opensm/osm_base.h>
+#include <complib/cl_atomic.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Statistics
+* NAME
+* OpenSM
+*
+* DESCRIPTION
+* The OpenSM object encapsulates the information needed by the
+* OpenSM to track interesting traffic and internal statistics.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Statistics/osm_stats_t
+* NAME
+* osm_stats_t
+*
+* DESCRIPTION
+* OpenSM statistics block.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_stats
+{
+ atomic32_t qp0_mads_outstanding;
+ atomic32_t qp0_mads_outstanding_on_wire;
+ atomic32_t qp0_mads_rcvd;
+ atomic32_t qp0_mads_sent;
+ atomic32_t qp0_unicasts_sent;
+ atomic32_t qp1_mads_outstanding;
+ atomic32_t qp1_mads_rcvd;
+ atomic32_t qp1_mads_sent;
+
+} osm_stats_t;
+/*
+* FIELDS
+* qp0_mads_outstanding
+* Contains the number of MADs outstanding on QP0.
+* When this value reaches zero, OpenSM has discovered all
+* nodes on the subnet, and finished retrieving attributes.
+* At that time, subnet configuration may begin.
+* This variable must be manipulated using atomic instructions.
+*
+* qp0_mads_outstanding_on_wire
+* The number of MADs outstanding on the wire at any moment.
+*
+* qp0_mads_rcvd
+* Total number of QP0 MADs received.
+*
+* qp0_mads_sent
+* Total number of QP0 MADs sent.
+*
+* qp0_unicasts_sent
+* Total number of response-less MADs sent on the wire. This count
+* includes getresp(), send() and trap() methods.
+*
+* SEE ALSO
+***************/
+
+END_C_DECLS
+
+#endif /* _OSM_STATS_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#ifndef _OSM_SUBNET_H_
+#define _OSM_SUBNET_H_
+
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <complib/cl_ptr_vector.h>
+#include <complib/cl_list.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_SUBNET_VECTOR_MIN_SIZE 0
+#define OSM_SUBNET_VECTOR_GROW_SIZE 1
+#define OSM_SUBNET_VECTOR_CAPACITY 256
+
+
+/****h* OpenSM/Subnet
+* NAME
+* Subnet
+*
+* DESCRIPTION
+* The Subnet object encapsulates the information needed by the
+* OpenSM to manage a subnet. The OpenSM allocates one Subnet object
+* per IBA subnet.
+*
+* The Subnet object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object is essentially a container for the various components
+* of a subnet. Callers may directly access the member variables.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_extension
+* NAME
+* osm_pfn_ui_extension
+*
+* DESCRIPTION
+* This typedef defines the prototype for UI extension functions
+* The might be registered in the subnet options to handle pre_lid_assign,
+* and ui_ucast_fwd_assign.
+*
+* SYNOPSIS
+*/
+typedef int
+(*osm_pfn_ui_extension_t)(
+ IN void* context);
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in the subnet opt
+* Same prefix as the UI funciton (suffixed by ctx)
+*
+* RETURN VALUE
+* This function returns an int (the semantic is different between
+* the different calls)
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_mcast_extension
+* NAME
+* osm_pfn_ui_mcast_extension
+*
+* DESCRIPTION
+* This typedef defines the prototype for UI extension functions
+* They might be registered in the subnet options to handle ui_mcast_fwd_assign
+*
+* SYNOPSIS
+*/
+typedef void
+(*osm_pfn_ui_mcast_extension_t)(
+ IN void *context,
+ IN ib_net16_t mlid,
+ IN osm_mcast_req_type_t request_type,
+ IN ib_net64_t port_guid );
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in the subnet opt
+* Same prefix as the UI funciton (suffixed by ctx)
+*
+* mlid
+* [in] multicast lid of the group handled.
+*
+* request_type
+* [in] Type of MC request being handled (create/join/leave)
+*
+* port_guid
+* [in] port gui of the port that was added/removed from the
+* multicast group handled.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* SEE ALSO
+*
+*********/
+
+/****d* OpenSM: Subnet/osm_testability_modes_t
+* NAME
+* osm_testability_modes_t
+*
+* DESCRIPTION
+* Enumerates the possible testability modes.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_testability_modes
+{
+ OSM_TEST_MODE_NONE = 0,
+ OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER,
+ OSM_TEST_MODE_MAX
+
+} osm_testability_modes_t;
+/***********/
+
+/****s* OpenSM: Subnet/osm_subn_opt_t
+* NAME
+* osm_subn_opt_t
+*
+* DESCRIPTION
+* Subnet options structure. This structure contains the various
+* site specific configuration parameters for the subnet.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn_opt
+{
+ ib_net64_t m_key;
+ ib_net64_t sm_key;
+ ib_net64_t subnet_prefix;
+ ib_net16_t m_key_lease_period;
+ uint32_t sweep_interval;
+ uint32_t max_wire_smps;
+ uint32_t transaction_timeout;
+ uint8_t sm_priority;
+ uint8_t lmc;
+ uint8_t max_op_vls;
+ boolean_t reassign_lids;
+ boolean_t reassign_lfts;
+ boolean_t ignore_other_sm;
+ boolean_t single_thread;
+ boolean_t no_multicast_option;
+ boolean_t disable_multicast;
+ boolean_t force_log_flush;
+ uint8_t subnet_timeout;
+ uint8_t packet_life_time;
+ uint8_t head_of_queue_lifetime;
+ uint8_t leaf_head_of_queue_lifetime;
+ uint8_t local_phy_errors_threshold;
+ uint8_t overrun_errors_threshold;
+ uint32_t sminfo_polling_timeout;
+ uint32_t polling_retry_number;
+ uint32_t max_msg_fifo_timeout;
+ boolean_t force_heavy_sweep;
+ uint8_t log_flags;
+ char * dump_files_dir;
+ char * log_file;
+ cl_map_t port_pro_ignore_guids;
+ boolean_t port_profile_switch_nodes;
+ uint32_t max_port_profile;
+ osm_pfn_ui_extension_t pfn_ui_pre_lid_assign;
+ void * ui_pre_lid_assign_ctx;
+ osm_pfn_ui_extension_t pfn_ui_ucast_fdb_assign;
+ void * ui_ucast_fdb_assign_ctx;
+ osm_pfn_ui_mcast_extension_t pfn_ui_mcast_fdb_assign;
+ void * ui_mcast_fdb_assign_ctx;
+ boolean_t sweep_on_trap;
+ osm_testability_modes_t testability_mode;
+ boolean_t updn_activate;
+ char * updn_guid_file;
+} osm_subn_opt_t;
+/*
+* FIELDS
+*
+* m_key
+* M_Key value sent to all ports qualifing all Set(PortInfo).
+*
+* sm_key
+* SM_Key value of the SM to qualify rcv SA queries as "trusted".
+*
+* subnet_prefix
+* Subnet prefix used on this subnet.
+*
+* m_key_lease_period
+* The lease period used for the M_Key on this subnet.
+*
+* sweep_interval
+* The number of seconds between subnet sweeps. A value of 0
+* disables sweeping.
+*
+* sm_priority
+* The priority of this SM as specified by the user. This
+* value is made available in the SMInfo attribute.
+*
+* lmc
+* The LMC value used on this subnet.
+*
+* max_op_vls
+* Limit the maximal operational VLs. default is 1.
+*
+* reassign_lids
+* If TRUE cause all lids to be re-assigend.
+* Otherwise (the default)
+* OpenSM always try to preserve as much LIDs as posible.
+*
+* reassign_lfts
+* If TRUE ignore existing LFT entries on first sweep (default).
+* Otherwise only non minimal hop cases are modified.
+* NOTE: A standby SM clears its first sweep flag - since the
+* master SM already sweeps...
+*
+* ignore_other_sm_option
+* This flag is TRUE if other SM's on the subnet should be ignored.
+*
+* no_multicast_option
+* This flag is TRUE if OpenSM should disable multicast support.
+*
+* max_msg_fifo_timeout
+* The maximal time a message can stay in the incoming message queue.
+* If there is more then one message in the queue and the last message
+* stayed in the queue more then this value the SA request will be
+* immediately returned with a BUSY status.
+*
+* subnet_timeout
+* The subnet_timeout that will be set for all the ports in the
+* design SubnMgt.Set(PortInfo.vl_stall_life))
+*
+* head_of_queue_lifetime
+* The maximal time a packet can live at the head of a VL queue
+* on any port not driving an HCA port
+*
+* leaf_head_of_queue_lifetime
+* The maximal time a packet can live at the head of a VL queue
+* on switch ports driving a CA
+*
+* local_phy_errors_threshold
+* Threshold of local phy errors for sending Trap 129
+*
+* overrun_errors_threshold
+* Threshold of credits over-run errors for sending Trap 129
+*
+* sminfo_polling_timeout
+* Specifies the polling timeout (in milliseconds) - the timeout
+* between one poll to another.
+*
+* packet_life_time
+* The maximal time a packet can stay in a switch.
+* The value is send to all switches as SubnMgt.Set(SwitchInfo.life_state)
+*
+* dump_files_dir
+* The directory to be used for subnet.lst osm.fdbs, osm.mcfdbs and default
+* log file (the latter for Windows, not Linux);
+*
+* log_file
+* Name of the log file (or NULL) for stdout.
+*
+* port_pro_ignore_guids
+* A map of guids to be ignored by port profiling.
+*
+* port_profile_switch_nodes
+* If TRUE will count the number of switch nodes routed through
+* the link. If FALSE - only CA/RT nodes are counted.
+*
+* max_port_profile
+* Prevent routing through a port subscribed with more then this
+* number of routes.
+*
+* pfn_ui_pre_lid_assign
+* A UI function to be invoked prior to lid assigment. It should return 1
+* if any change was made to any lid or 0 otherwise.
+*
+* ui_pre_lid_assign_ctx
+* A UI context (void *) to be provided to the pfn_ui_pre_lid_assign
+*
+* pfn_ui_ucast_fdb_assign
+* A UI function to be called instead of the ucast manager FDB
+* configuration.
+*
+* ui_ucast_fdb_assign_ctx
+* A UI context (void *) to be provided to the pfn_ui_ucast_fdb_assign
+*
+* pfn_ui_mcast_fdb_assign
+* A UI function to be called inside the mcast manager instead of the
+* call for the build spanning tree. This will be called on every
+* multicast call for create, join and leave, and is responsible for
+* the mcast FDB configuration.
+*
+* ui_mcast_fdb_assign_ctx
+* A UI context (void *) to be provided to the pfn_ui_mcast_fdb_assign
+*
+* sweep_on_trap
+* Received traps will initiate a new sweep.
+*
+* testability_mode
+* Object that indicates if we are running in a special testability mode.
+*
+* updn_activate
+* Object that indicates if we are running the UPDN algorithm (TRUE) or
+* Min Hop Algorithm (FALSE)
+*
+* updn_guid_file
+* Pointer to name of the UPDN guid file given by User
+*
+* SEE ALSO
+* Subnet object
+*********/
+
+/****s* OpenSM: Subnet/osm_subn_t
+* NAME
+* osm_subn_t
+*
+* DESCRIPTION
+* Subnet structure. Callers may directly access member components,
+* after grabbing a lock.
+*
+* TO DO
+* This structure should probably be volatile.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn
+{
+ cl_qmap_t sw_guid_tbl;
+ cl_qmap_t node_guid_tbl;
+ cl_qmap_t port_guid_tbl;
+ cl_qmap_t rtr_guid_tbl;
+ cl_qmap_t prtn_pkey_tbl;
+ cl_qmap_t mgrp_mlid_tbl;
+ cl_qmap_t sm_guid_tbl;
+ cl_list_t light_sweep_physp_list;
+ cl_qlist_t sa_sr_list;
+ cl_qlist_t sa_infr_list;
+ cl_ptr_vector_t node_lid_tbl;
+ cl_ptr_vector_t port_lid_tbl;
+ ib_net16_t master_sm_base_lid;
+ ib_net16_t sm_base_lid;
+ ib_net64_t sm_port_guid;
+ uint8_t sm_state;
+ osm_subn_opt_t opt;
+ uint16_t max_unicast_lid_ho;
+ uint16_t max_multicast_lid_ho;
+ uint8_t min_ca_mtu;
+ uint8_t min_ca_rate;
+ boolean_t ignore_existing_lfts;
+ boolean_t subnet_initialization_error;
+ boolean_t force_immediate_heavy_sweep;
+ boolean_t force_delayed_heavy_sweep;
+ cl_list_t new_ports_list;
+ boolean_t in_sweep_hop_0;
+ boolean_t moved_to_master_state;
+ boolean_t first_time_master_sweep;
+ boolean_t coming_out_of_standby;
+} osm_subn_t;
+/*
+* FIELDS
+* sw_guid_tbl
+* Container of pointers to all Switch objects in the subent.
+* Indexed by node GUID.
+*
+* node_guid_tbl
+* Container of pointers to all Node objects in the subent.
+* Indexed by node GUID.
+*
+* port_guid_tbl
+* Container of pointers to all Port objects in the subent.
+* Indexed by port GUID - network order!
+*
+* rtr_guid_tbl
+* Container of pointers to all Router objects in the subent.
+* Indexed by node GUID.
+*
+* prtn_pkey_tbl
+* Container of pointers to all Partition objects in the subnet.
+* Indexed by P_KEY.
+*
+* mgrp_mlid_tbl
+* Container of pointers to all Multicast Group objects in the subnet.
+* Indexed by MLID.
+*
+* sm_guid_tbl
+* Container of pointers to Other SM objects representing other SM's
+* on the subnet.
+*
+* light_sweep_physp_list
+* A list of all phys ports to scan for a change in remote
+* side state in next light sweep. These ports are not down
+* but for some reason the remote side did not answer.
+*
+* node_lid_tbl
+* Container of pointers to all Node objects in the subent.
+* Indexed by node LID.
+*
+* port_ptr_tbl
+* Container of pointers to all Port objects in the subent.
+* Indexed by port LID.
+*
+* master_sm_base_lid
+* The base LID owned by the subnet's master SM.
+*
+* sm_base_lid
+* The base LID of the local port where the SM is.
+*
+* sm_port_guid
+* This SM's own port GUID.
+*
+* sm_state
+* The high-level state of the SM. This value is made available
+* in the SMInfo attribute.
+*
+* opt
+* Subnet options structure contains site specific configuration.
+*
+* max_unicast_lid_ho
+* The minimal max unicast lid reported by all switches
+*
+* max_multicast_lid_ho
+* The minimal max multicast lid reported by all switches
+*
+* min_ca_mtu
+* The minimal MTU reported by all CAs ports on the subnet
+*
+* min_ca_rate
+* The minimal rate reported by all CA ports on the subnet
+*
+* ignore_existing_lfts
+* This flag is a dynamic flag to instruct the LFT asssign to
+* ignore existing legal LFT settings.
+* The value will be set according to :
+* - During SM init set to the reassign_lfts flag value
+* - Comming out of STANDBY it will be cleared (other SM worked)
+* - Any change to the list of switches will set it to high
+* - Set to FALSE on end of all lft assignments.
+*
+* subnet_initalization_error
+* Similar to the force_immediate_heavy_sweep flag. If TRUE -
+* means that we had errors during initialization (due to SubnSet requests
+* that failed). We want to declare the subnet as un-healthy, and force
+* another heavy sweep.
+*
+* force_immediate_heavy_sweep
+* If TRUE - we want to force a heavy sweep. This can be done either
+* due to receiving of trap - meaning there is some change on the subnet,
+* or we received a handover from a remote sm.
+* In this case we want to sweep and reconfigure the entire subnet.
+* This will cause another heavy sweep to occure when the current sweep
+* is done.
+*
+* force_delayed_heavy_sweep
+* In some means - similar to the force_immediate_heavy_sweep flag, only
+* it'll cause a heavy sweep in the next sweep. Note that this means that
+* if we are running with -s 0 (no sweeps) - then this forced heavy sweep
+* will not occur.
+* If we had some trouble on the subnet, that caused a strange dropping
+* of ports - we will try to do another heavy sweep on our next sweep.
+*
+* new_ports_list
+* Container of pointers to port objects that were discovered for
+* the first time during a current sweep.
+*
+* in_sweep_hop_0
+* When in_sweep_hop_0 flag is set to TRUE - this means we are
+* in sweep_hop_0 - meaning we do not want to continue beyond
+* the current node.
+* This is relevant for the case of SM on switch, since in the
+* switch info we need to signal somehow not to continue
+* the sweeping.
+*
+* moved_to_master_state
+* Used for the writing of "SUBNET UP" into /var/log/messages.
+* Will be TRUE when the SM switches to Master state, and returned
+* to FALSE once the sunbet is up.
+*
+* first_time_master_sweep
+* This flag is used for the PortInfo setting. On the first sweep as master
+* (meaning after moving from Standby|Discovering state), the SM must send
+* a PortInfoSet to all ports. After that - we want to minimize the number of
+* PortInfoSet requests sent, and to send only requests that change the value
+* from what is updated in the port (or send a first request if this is a new port).
+* We will set this flag to TRUE when entering the master state, and set it back
+* to FALSE at the end of the drop manager. This is done since at the end of the
+* drop manager we have updated all the ports that are reachable, and from now on
+* these are the only ports we have data of. We don't want to send extra set requests
+* to these ports anymore.
+*
+* coming_out_of_standby
+* TRUE on the first sweep after the SM was in standby.
+* Used for nulling any cache of LID and Routing.
+* The flag is set true if the SM state was standby and now changed to MASTER
+* it is reset at the end of the sweep.
+*
+* SEE ALSO
+* Subnet object
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_construct
+* NAME
+* osm_subn_construct
+*
+* DESCRIPTION
+* This function constructs a Subnet object.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_construct(
+ IN osm_subn_t* const p_subn );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to a Subnet object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_subn_init, osm_subn_destroy, and osm_subn_is_inited.
+*
+* Calling osm_subn_construct is a prerequisite to calling any other
+* method except osm_subn_init.
+*
+* SEE ALSO
+* Subnet object, osm_subn_init, osm_subn_destroy, osm_subn_is_inited
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_destroy
+* NAME
+* osm_subn_destroy
+*
+* DESCRIPTION
+* The osm_subn_destroy function destroys a subnet, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_destroy(
+ IN osm_subn_t* const p_subn );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to a Subnet object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Subnet object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_subn_construct or
+* osm_subn_init.
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_init
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_init
+* NAME
+* osm_subn_init
+*
+* DESCRIPTION
+* The osm_subn_init function initializes a Subnet object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_subn_init(
+ IN osm_subn_t* const p_subn,
+ IN const osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object to initialize.
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Subnet object was initialized successfully.
+*
+* NOTES
+* Allows calling other Subnet methods.
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited
+*********/
+
+/*
+ Forward reference.
+*/
+struct _osm_mad_addr;
+struct _osm_log;
+struct _osm_switch;
+struct _osm_physp;
+struct _osm_port;
+
+/****f* OpenSM: Helper/osm_get_gid_by_mad_addr
+* NAME
+* osm_get_gid_by_mad_addr
+*
+* DESCRIPTION
+* Looks for the requestor gid in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+ib_gid_t
+osm_get_gid_by_mad_addr(
+ IN struct _osm_log *p_log,
+ IN const osm_subn_t *p_subn,
+ IN const struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to subnet object.
+*
+* p_mad_addr
+* [in] Pointer to mad address object.
+*
+* RETURN VALUES
+* Requestor gid object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+* osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+* Looks for the requestor physical port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_physp *
+osm_get_physp_by_mad_addr(
+ IN struct _osm_log *p_log,
+ IN const osm_subn_t *p_subn,
+ IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to subnet object.
+*
+* p_mad_addr
+* [in] Pointer to mad address object.
+*
+* RETURN VALUES
+* Pointer to requestor physical port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_get_port_by_mad_addr
+* NAME
+* osm_get_port_by_mad_addr
+*
+* DESCRIPTION
+* Looks for the requestor port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_port *
+osm_get_port_by_mad_addr(
+ IN struct _osm_log *p_log,
+ IN const osm_subn_t *p_subn,
+ IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to subnet object.
+*
+* p_mad_addr
+* [in] Pointer to mad address object.
+*
+* RETURN VALUES
+* Pointer to requestor port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Subnet/osm_get_switch_by_guid
+* NAME
+* osm_get_switch_by_guid
+*
+* DESCRIPTION
+* The looks for the given switch guid in the subnet table of switches by guid.
+* NOTE: this code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_switch *
+osm_get_switch_by_guid(
+ IN const osm_subn_t *p_subn,
+ IN uint64_t guid);
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The node guid in host order
+*
+* RETURN VALUES
+* The switch structure pointer if found. NULL otherwise.
+* NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO g529
+
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited, osm_switch_t
+*********/
+/****f* OpenSM: Subnet/osm_get_node_by_guid
+* NAME
+* osm_get_node_by_guid
+*
+* DESCRIPTION
+* The looks for the given node giud in the subnet table of nodes by guid.
+* NOTE: this code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_node *
+osm_get_node_by_guid(
+ IN osm_subn_t const *p_subn,
+ IN uint64_t guid);
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The node guid in host order
+*
+* RETURN VALUES
+* The node structure pointer if found. NULL otherwise.
+* NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited, osm_node_t
+*********/
+
+/****f* OpenSM: Subnet/osm_get_port_by_guid
+* NAME
+* osm_get_port_by_guid
+*
+* DESCRIPTION
+* The looks for the given port guid in the subnet table of ports by guid.
+* NOTE: this code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_port *
+osm_get_port_by_guid(
+ IN osm_subn_t const *p_subn,
+ IN uint64_t guid);
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The port guid in host order
+*
+* RETURN VALUES
+* The port structure pointer if found. NULL otherwise.
+* NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited, osm_port_t
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+* osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+* Looks for the requestor physical port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_physp *
+osm_get_physp_by_mad_addr(
+ IN struct _osm_log *p_log,
+ IN const osm_subn_t *p_subn,
+ IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to subnet object.
+*
+* p_mad_addr
+* [in] Pointer to mad address object.
+*
+* RETURN VALUES
+* Pointer to requestor physical port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_set_default_opt
+* NAME
+* osm_subn_set_default_opt
+*
+* DESCRIPTION
+* The osm_subn_set_default_opt function sets the default options.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_set_default_opt(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_set_default_opt
+* NAME
+* osm_subn_set_default_opt
+*
+* DESCRIPTION
+* The osm_subn_set_default_opt function sets the default options.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_set_default_opt(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_parse_conf_file
+* NAME
+* osm_subn_parse_conf_file
+*
+* DESCRIPTION
+* The osm_subn_parse_conf_file function parses the configuration file
+* and sets the defaults accordingly.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_parse_conf_file(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* Assumes the conf file is part of the cache dir which defaults to
+* OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_write_conf_file
+* NAME
+* osm_subn_write_conf_file
+*
+* DESCRIPTION
+* Write the configuration file into the cache
+*
+* SYNOPSIS
+*/
+void
+osm_subn_write_conf_file(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* Assumes the conf file is part of the cache dir which defaults to
+* OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy,
+* osm_subn_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_subn_conf_ctrl_t.
+ * This object represents a controller that initiates configuration
+ * of the subnet after the discovery phase is complete.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SUBNET_CONFIG_CTRL_H_
+#define _OSM_SUBNET_CONFIG_CTRL_H_
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Subnet Configuration Controller
+* NAME
+* Subnet Configuration Controller
+*
+* DESCRIPTION
+* The Subnet Configuration Controller object encapsulates the
+* information needed to initiate a subnet configuration pass.
+* The Subnet Configuration Controller sends Dispatcher messages
+* to controllers responsible for configuring LIDs,
+* switch forwarding tables, etc.
+*
+* The Subnet Configuration Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_t
+* NAME
+* osm_subn_conf_ctrl_t
+*
+* DESCRIPTION
+* Subnet Configuration Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn_conf_ctrl
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_dispatcher_t *p_disp;
+
+} osm_subn_conf_ctrl_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* SEE ALSO
+* Subnet Configuration Controller object
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_construct
+* NAME
+* osm_subn_conf_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Subnet Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_subn_conf_ctrl_construct(
+ IN osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Subnet Configuration Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_subn_conf_ctrl_init, osm_subn_conf_ctrl_destroy,
+* and osm_subn_conf_ctrl_is_inited.
+*
+* Calling osm_subn_conf_ctrl_construct is a prerequisite to calling any other
+* method except osm_subn_conf_ctrl_init.
+*
+* SEE ALSO
+* Subnet Configuration Controller object, osm_subn_conf_ctrl_init,
+* osm_subn_conf_ctrl_destroy, osm_subn_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_destroy
+* NAME
+* osm_subn_conf_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_subn_conf_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_subn_conf_ctrl_destroy(
+ IN osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Subnet Configuration Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_subn_conf_ctrl_construct or osm_subn_conf_ctrl_init.
+*
+* SEE ALSO
+* Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+* osm_subn_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_init
+* NAME
+* osm_subn_conf_ctrl_init
+*
+* DESCRIPTION
+* The osm_subn_conf_ctrl_init function initializes a
+* Subnet Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_subn_conf_ctrl_init(
+ IN osm_subn_conf_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_subn_conf_ctrl_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Subnet Configuration Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Subnet Configuration Controller methods.
+*
+* SEE ALSO
+* Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+* osm_subn_conf_ctrl_destroy, osm_subn_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_is_inited
+* NAME
+* osm_subn_conf_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_subn_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_subn_conf_ctrl_is_inited(
+ IN const osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_subn_conf_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_subn_conf_ctrl_construct or osm_subn_conf_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+* osm_subn_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_process
+* NAME
+* osm_subn_conf_ctrl_process
+*
+* DESCRIPTION
+* Initiate a subnet configuration pass.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_subn_conf_ctrl_process(
+ IN const osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_subn_conf_ctrl_t object.
+*
+* RETURN VALUES
+* IB_SUCCESS if configuration processing was successfully
+* initiated.
+*
+* NOTES
+* A success status here does not indicate that
+* the entire subnet configuration process completed successfully.
+* Only one configuration pass is active at one time.
+*
+* SEE ALSO
+* Subnet Configuration Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_CONFIG_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SI_RCV_H_
+#define _OSM_SI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receiver
+* NAME
+* Switch Info Receiver
+*
+* DESCRIPTION
+* The Switch Info Receiver object encapsulates the information
+* needed to receive the SwitchInfo attribute from a node.
+*
+* The Switch Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Switch Info Receiver/osm_si_rcv_t
+* NAME
+* osm_si_rcv_t
+*
+* DESCRIPTION
+* Switch Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_req_t *p_req;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_si_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_req
+* Pointer to the Request object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_construct
+* NAME
+* osm_si_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_construct(
+ IN osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_si_rcv_init, osm_si_rcv_destroy,
+* and osm_si_rcv_is_inited.
+*
+* Calling osm_si_rcv_construct is a prerequisite to calling any other
+* method except osm_si_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_init,
+* osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_destroy
+* NAME
+* osm_si_rcv_destroy
+*
+* DESCRIPTION
+* The osm_si_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_destroy(
+ IN osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Switch Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_si_rcv_construct or osm_si_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_init
+* NAME
+* osm_si_rcv_init
+*
+* DESCRIPTION
+* The osm_si_rcv_init function initializes a
+* Switch Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_init(
+ IN osm_si_rcv_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Switch Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receiver methods.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_is_inited
+* NAME
+* osm_si_rcv_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_si_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_is_inited(
+ IN const osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_si_rcv_construct or osm_si_rcv_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_process
+* NAME
+* osm_si_rcv_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_process(
+ IN const osm_si_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* Switch Info Receiver, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_si_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA SwitchInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SI_RCV_CTRL_H_
+#define _OSM_SI_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receive Controller
+* NAME
+* Switch Info Receive Controller
+*
+* DESCRIPTION
+* The Switch Info Receive Controller object encapsulates
+* the information needed to receive the SwitchInfo attribute from a node.
+*
+* The Switch Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_t
+* NAME
+* osm_si_rcv_ctrl_t
+*
+* DESCRIPTION
+* Switch Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv_ctrl
+{
+ osm_si_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_si_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Switch Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Switch Info Receive Controller object
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_construct
+* NAME
+* osm_si_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_construct(
+ IN osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_si_rcv_ctrl_init, osm_si_rcv_ctrl_destroy,
+* and osm_si_rcv_ctrl_is_inited.
+*
+* Calling osm_si_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_init,
+* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_destroy
+* NAME
+* osm_si_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_si_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_destroy(
+ IN osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Switch Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_init
+* NAME
+* osm_si_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_si_rcv_ctrl_init function initializes a
+* Switch Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_ctrl_init(
+ IN osm_si_rcv_ctrl_t* const p_ctrl,
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Switch Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receive Controller methods.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_is_inited
+* NAME
+* osm_si_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_si_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_ctrl_is_inited(
+ IN const osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sweep_fail_ctrl_t.
+ * This object represents a controller that
+ * handles transport failures during sweeps.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_SWEEP_FAIL_CTRL_H_
+#define _OSM_SWEEP_FAIL_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Sweep Fail Controller
+* NAME
+* Sweep Fail Controller
+*
+* DESCRIPTION
+* The Sweep Fail Controller object encapsulates
+* the information needed to handle transport failures during
+* sweeps.
+*
+* The Sweep Fail Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_t
+* NAME
+* osm_sweep_fail_ctrl_t
+*
+* DESCRIPTION
+* Sweep Fail Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sweep_fail_ctrl
+{
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+
+} osm_sweep_fail_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_sate_mgr
+* Pointer to the state manager object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Sweep Fail Controller object
+* Sweep Failr object
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_construct
+* NAME
+* osm_sweep_fail_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Sweep Fail Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_construct(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Sweep Fail Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sweep_fail_ctrl_init, osm_sweep_fail_ctrl_destroy
+*
+* Calling osm_sweep_fail_ctrl_construct is a prerequisite to calling any other
+* method except osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_init,
+* osm_sweep_fail_ctrl_destroy
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_destroy
+* NAME
+* osm_sweep_fail_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sweep_fail_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_destroy(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Sweep Fail Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sweep_fail_ctrl_construct or osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+* osm_sweep_fail_ctrl_init
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_init
+* NAME
+* osm_sweep_fail_ctrl_init
+*
+* DESCRIPTION
+* The osm_sweep_fail_ctrl_init function initializes a
+* Sweep Fail Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sweep_fail_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sweep_fail_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the state manager object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Sweep Fail Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Sweep Fail Controller methods.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+* osm_sweep_fail_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWEEP_FAIL_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_switch_t.
+ * This object represents an IBA switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SWITCH_H_
+#define _OSM_SWITCH_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+#include <opensm/osm_port_profile.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch
+* NAME
+* Switch
+*
+* DESCRIPTION
+* The Switch object encapsulates the information needed by the
+* OpenSM to manage switches. The OpenSM allocates one switch object
+* per switch in the IBA subnet.
+*
+* The Switch object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****h* OpenSM/Switch
+* NAME
+* Switch
+*
+* DESCRIPTION
+* The Switch object encapsulates the information needed by the
+* OpenSM to manage switches. The OpenSM allocates one switch object
+* per switch in the IBA subnet.
+*
+* The Switch object is not thread safe, thus callers must provide
+* serialization.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Switch/osm_switch_t
+* NAME
+* osm_switch_t
+*
+* DESCRIPTION
+* Switch structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_switch
+{
+ cl_map_item_t map_item;
+ osm_node_t *p_node;
+ ib_switch_info_t switch_info;
+ osm_fwd_tbl_t fwd_tbl;
+ osm_lid_matrix_t lmx;
+ osm_port_profile_t *p_pro;
+ osm_mcast_tbl_t mcast_tbl;
+ uint32_t discovery_count;
+
+} osm_switch_t;
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* p_node
+* Pointer to the Node object for this switch.
+*
+* switch_info
+* IBA defined SwitchInfo structure for this switch.
+*
+* fwd_tbl
+* This switch's forwarding table.
+*
+* lmx
+* LID Matrix for this switch containing the hop count
+* to every LID from every port.
+*
+* p_pro
+* Pointer to array of Port Profile objects for this switch.
+*
+* mcast_tbl
+* Multicast forwarding table for this switch.
+*
+* discovery_count
+* The number of times this switch has been discovered
+* during the current fabric sweep. This number is reset
+* to zero at the start of a sweep.
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_construct
+* NAME
+* osm_switch_construct
+*
+* DESCRIPTION
+* This function constructs a Switch object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_construct(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_switch_init, osm_switch_destroy, and osm_switch_is_inited.
+*
+* Calling osm_switch_construct is a prerequisite to calling any other
+* method except osm_switch_init.
+*
+* SEE ALSO
+* Switch object, osm_switch_init, osm_switch_destroy, osm_switch_is_inited
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+* osm_switch_destroy
+*
+* DESCRIPTION
+* The osm_switch_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_destroy(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+* Performs any necessary cleanup of the specified object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_switch_construct
+* or osm_switch_init.
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+* osm_switch_destroy
+*
+* DESCRIPTION
+* Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_delete(
+ IN OUT osm_switch_t** const pp_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+
+/****f* OpenSM: Switch/osm_switch_init
+* NAME
+* osm_switch_init
+*
+* DESCRIPTION
+* The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_switch_init(
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object to initialize.
+*
+* p_node
+* [in] Pointer to the node object of this switch
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the switch's
+* SwitchInfo attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Switch object was initialized successfully.
+*
+* NOTES
+* Allows calling other node methods.
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_destroy,
+* osm_switch_is_inited
+*********/
+/****f* OpenSM: Switch/osm_switch_new
+* NAME
+* osm_switch_new
+*
+* DESCRIPTION
+* The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+osm_switch_t*
+osm_switch_new(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to the node object of this switch
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the switch's
+* SwitchInfo attribute.
+*
+* RETURN VALUES
+* Pointer to the new initialized switch object.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_destroy,
+*********/
+
+/****f* OpenSM: Switch/osm_switch_is_leaf_lid
+* NAME
+* osm_switch_is_leaf_lid
+*
+* DESCRIPTION
+* Indicates if the specified LID is the switch's LID, or is a leaf
+* of the switch.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_is_leaf_lid(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) <= 1 );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* lid_ho
+* [in] LID (host order) to compare.
+*
+* RETURN VALUES
+* TRUE if the LID is the switch's LID or is a leaf of the switch,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_hop_count
+* NAME
+* osm_switch_get_hop_count
+*
+* DESCRIPTION
+* Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_hop_count(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num )
+{
+ return( osm_lid_matrix_get( &p_sw->lmx, lid_ho, port_num ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to return the hop count
+*
+* port_num
+* [in] Port number in the switch
+*
+* RETURN VALUES
+* Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_ptr
+* NAME
+* osm_switch_get_fwd_tbl_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the switch's forwarding table.
+*
+* SYNOPSIS
+*/
+static inline osm_fwd_tbl_t*
+osm_switch_get_fwd_tbl_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (osm_fwd_tbl_t*)&p_sw->fwd_tbl );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* RETURN VALUES
+* Returns a pointer to the switch's forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_hops
+* NAME
+* osm_switch_set_hops
+*
+* DESCRIPTION
+* Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_switch_set_hops(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t num_hops )
+{
+ return( osm_lid_matrix_set( &p_sw->lmx, lid_ho, port_num, num_hops ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the count.
+*
+* port_num
+* [in] port number for which to set the count.
+*
+* num_hops
+* [in] value to assign to this entry.
+*
+* RETURN VALUES
+* Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_hops
+* NAME
+* osm_switch_set_hops
+*
+* DESCRIPTION
+* Sets the size of the switch's routing table to at least accomodate the
+* specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_switch_set_min_lid_size(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_set_min_lid_size( &p_sw->lmx, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the count.
+*
+* RETURN VALUES
+* Sets the size of the switch's routing table to at least accomodate the
+* specified LID value (host ordered)
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_least_hops
+* NAME
+* osm_switch_get_least_hops
+*
+* DESCRIPTION
+* Returns the number of hops in the short path to this lid from
+* any port on the switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_least_hops(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* lid_ho
+* [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+* Returns the number of hops in the short path to this lid from
+* any port on the switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_port_by_lid
+* NAME
+* osm_switch_get_port_by_lid
+*
+* DESCRIPTION
+* Returns the switch port number on which the specified LID is routed.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_port_by_lid(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* lid_ho
+* [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+* Returns the switch port on which the specified LID is routed.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_lid
+* NAME
+* osm_switch_get_lid
+*
+* DESCRIPTION
+* Gets the switch's LID.
+*
+* SYNOPSIS
+*/
+ib_net16_t
+osm_switch_get_lid(
+ IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the switch's LID. A value of zero means no LID has
+* been assigned to the switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_physp_ptr
+* NAME
+* osm_switch_get_physp_ptr
+*
+* DESCRIPTION
+* Gets the Physical Port Object at the specified port number.
+*
+* SYNOPSIS
+*/
+osm_physp_t*
+osm_switch_get_physp_ptr(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t port_num );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* port_num
+* [in] Port number for which to retrieve the Physical Port Object.
+*
+* RETURN VALUES
+* Returns a pointer to the Physical Port Object object at the specified
+* port number.
+* A return value of zero means the port number was out of range.
+*
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_route_by_lid
+* NAME
+* osm_switch_get_route_by_lid
+*
+* DESCRIPTION
+* Gets the physical port object that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_switch_get_route_by_lid(
+ IN const osm_switch_t* const p_sw,
+ IN const ib_net16_t lid )
+{
+ uint8_t port_num;
+ CL_ASSERT( p_sw );
+ CL_ASSERT( lid );
+
+ port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, cl_ntoh16( lid ) );
+ /*
+ In order to avoid holes in the subnet (usually happens when
+ running UPDN alogrithm ), i.e. cases where port is
+ unreachable through a switch (we put a OSM_NO_PATH value at
+ the port entry , we do not assert on unreachable lids entries
+ at the fwd table but return NULL
+ */
+ if (port_num != OSM_NO_PATH)
+ return( osm_node_get_physp_ptr( p_sw->p_node, port_num ) );
+ else
+ return NULL;
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* lid
+* [in] LID for which to find a route. This must be a unicast
+* LID value < 0xC000.
+*
+* RETURN VALUES
+* Returns a pointer to the Physical Port Object object that
+* routes the specified LID. A return value of zero means
+* there is no route for the lid through this switch.
+* The lid value must be a unicast LID.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_si_ptr
+* NAME
+* osm_switch_get_si_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the SwitchInfo for this switch.
+*
+* SYNOPSIS
+*/
+static inline ib_switch_info_t*
+osm_switch_get_si_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (ib_switch_info_t*)&p_sw->switch_info );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the SwitchInfo for this switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block_id
+* NAME
+* osm_switch_get_max_block_id
+*
+* DESCRIPTION
+* Returns the maximum block ID (host order) of this switch.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_get_max_block_id(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (uint32_t)(osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) /
+ osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl ) ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the maximum block ID (host order) of this switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use
+* NAME
+* osm_switch_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the maximum block ID (host order) of this switch that
+* is used for unicast routing.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_get_max_block_id_in_use(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_fwd_tbl_get_max_block_id_in_use( &p_sw->fwd_tbl,
+ cl_ntoh16( p_sw->switch_info.lin_top ) ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the maximum block ID (host order) of this switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_node_ptr
+* NAME
+* osm_switch_get_node_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the Node object for this switch.
+*
+* SYNOPSIS
+*/
+static inline osm_node_t*
+osm_switch_get_node_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( p_sw->p_node );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the LID matrix for this switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_lid_ho
+* NAME
+* osm_switch_get_max_lid_ho
+*
+* DESCRIPTION
+* Returns the maximum LID (host order) value contained
+* in the switch routing tables.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_max_lid_ho(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_lid_matrix_get_max_lid_ho( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a switch object.
+*
+* RETURN VALUES
+* Returns the maximum LID (host order) value contained
+* in the switch routing tables.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_num_ports
+* NAME
+* osm_switch_get_num_ports
+*
+* DESCRIPTION
+* Returns the number of ports in this switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_num_ports(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_lid_matrix_get_num_ports( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the number of ports in this switch.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_block
+* NAME
+* osm_switch_get_fwd_tbl_block
+*
+* DESCRIPTION
+* Retrieve a forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t block_id,
+ OUT uint8_t* const p_block );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* block_ID
+* [in] The block_id to retrieve.
+*
+* p_block
+* [out] Pointer to the 64 byte array to store the
+* forwarding table clock specified by block_id.
+*
+* RETURN VALUES
+* Returns true if there are more blocks necessary to
+* configure all the LIDs reachable from this switch.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Switch/osm_switch_supports_mcast
+* NAME
+* osm_switch_supports_mcast
+*
+* DESCRIPTION
+* Indicates if a switch supports multicast.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_supports_mcast(
+ IN const osm_switch_t* const p_sw )
+{
+ return( p_sw->switch_info.mcast_cap != 0 );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns TRUE if the switch supports multicast.
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_switch_info
+* NAME
+* osm_switch_set_switch_info
+*
+* DESCRIPTION
+* Updates the switch info attribute of this switch.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_set_switch_info(
+ IN osm_switch_t* const p_sw,
+ IN const ib_switch_info_t* const p_si )
+{
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_si );
+ p_sw->switch_info = *p_si;
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* p_si
+* [in] Pointer to the SwitchInfo attribute for this switch.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_path
+* NAME
+* osm_switch_set_path
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_set_path(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port,
+ IN const boolean_t ignore_port_pro
+ )
+{
+ CL_ASSERT( p_sw );
+ osm_fwd_tbl_set( &p_sw->fwd_tbl, lid_ho, port );
+ if (! ignore_port_pro)
+ osm_port_pro_path_count_inc( &p_sw->p_pro[port] );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_ft_block
+* NAME
+* osm_switch_set_ft_block
+*
+* DESCRIPTION
+* Copies in the specified block into the switch's Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_ft_block(
+ IN osm_switch_t* const p_sw,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ CL_ASSERT( p_sw );
+ return( osm_fwd_tbl_set_block( &p_sw->fwd_tbl, p_block, block_num ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* p_block
+* [in] Pointer to the forwarding table block.
+*
+* block_num
+* [in] Block number for this block
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_mft_block
+* NAME
+* osm_switch_set_mft_block
+*
+* DESCRIPTION
+* Sets a block of multicast port masks into the multicast table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_mft_block(
+ IN osm_switch_t* const p_sw,
+ IN const ib_net16_t* const p_block,
+ IN const uint16_t block_num,
+ IN const uint8_t position )
+{
+ CL_ASSERT( p_sw );
+ return( osm_mcast_tbl_set_block( &p_sw->mcast_tbl, p_block,
+ block_num, position ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* p_block
+* [in] Pointer to the block of port masks to set.
+*
+* block_num
+* [in] Block number (0-511) to set.
+*
+* position
+* [in] Port mask position (0-15) to set.
+*
+* RETURN VALUE
+* IB_SUCCESS on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_recommend_path
+* NAME
+* osm_switch_recommend_path
+*
+* DESCRIPTION
+* Returns the recommended port on which to route this LID.
+* In cases where LMC > 0, the remote side system and node
+* used for the routing are tracked in the provided arrays
+* (and counts) such that other lid for the same port will
+* try and avoid going through the same remote system/node.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_switch_recommend_path(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const boolean_t ignore_existing,
+ IN OUT uint64_t *remote_sys_guids,
+ IN OUT uint16_t *p_num_used_sys,
+ IN OUT uint64_t *remote_node_guids,
+ IN OUT uint16_t *p_num_used_nodes,
+ IN const uint32_t max_routes_subscribed,
+ IN boolean_t ui_ucast_fdb_assign_func_defined
+ );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get a path advisory.
+*
+* ignore_existing
+* [in] Set to cause the switch to choose the optimal route
+* regardless of existing paths.
+* If false, the switch will choose an existing route if one exists,
+* otherwise will choose the optimal route.
+*
+* remote_sys_guids
+* [in out] The array of remote system guids already used to route
+* the other lids of the same target port (if LMC > 0).
+*
+* p_num_used_sys
+* [in out] The number of remote systems used for routing to the port.
+*
+* remote_node_guids
+* [in out] The array of remote node guids already used to route
+* the other lids of the same target port (if LMC > 0).
+*
+* p_num_used_nodes
+* [in out] The number of remote nodes used for routing to the port.
+*
+* max_routes_subscribed
+* [in] The maximum allowed number of target lids routed through
+* a specific port of the switch. If the port already assigned
+* (in the lfdb) this number of target lids - it will not be used
+* even if it has the smallest hops count to the target lid.
+*
+* ui_ucast_fdb_assign_func_defined
+* [in] If TRUE - this means that there is a ui ucast_fdb_assign table
+* function defined (in pfn_ui_ucast_fdb_assign in subnet opts). This
+* means that all current entries in the fdbs will be used.
+* If FALSE - such function isn't defined. Do the minimum hop checks
+* before accepting the current fdbs.
+*
+* RETURN VALUE
+* Returns the recommended port on which to route this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_recommend_mcast_path
+* NAME
+* osm_switch_recommend_mcast_path
+*
+* DESCRIPTION
+* Returns the recommended port on which to route this LID.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_switch_recommend_mcast_path(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint16_t mlid_ho,
+ IN const boolean_t ignore_existing );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* lid_ho
+* [in] LID value (host order) for of the node for with to get
+* the multicast path.
+*
+* mlid_ho
+* [in] MLID for the multicast group in question.
+*
+* ignore_existing
+* [in] Set to cause the switch to choose the optimal route
+* regardless of existing paths.
+* If false, the switch will choose an existing route if one exists,
+* otherwise will choose the optimal route.
+*
+* RETURN VALUE
+* Returns the recommended port on which to route this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_size
+* NAME
+* osm_switch_get_fwd_tbl_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_fwd_tbl_size(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size
+* NAME
+* osm_switch_get_mcast_fwd_tbl_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the multicast forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_mcast_fwd_tbl_size(
+ IN const osm_switch_t* const p_sw )
+{
+ return( cl_ntoh16( p_sw->switch_info.mcast_cap ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch.
+*
+* RETURN VALUE
+* Returns the number of entries available in the multicast forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_path_count_get
+* NAME
+* osm_switch_path_count_get
+*
+* DESCRIPTION
+* Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_path_count_get(
+ IN const osm_switch_t* const p_sw,
+ IN const uint8_t port_num )
+{
+ return( osm_port_pro_path_count_get( &p_sw->p_pro[port_num] ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the Switch object.
+*
+* port_num
+* [in] Port number for which to get path count.
+*
+* RETURN VALUE
+* Returns the count of the number of paths going through this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_prepare_path_rebuild
+* NAME
+* osm_switch_prepare_path_rebuild
+*
+* DESCRIPTION
+* Prepares a switch to rebuild pathing information.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_prepare_path_rebuild(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the Switch object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr
+* NAME
+* osm_switch_get_mcast_tbl_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the switch's multicast table.
+*
+* SYNOPSIS
+*/
+static inline osm_mcast_tbl_t*
+osm_switch_get_mcast_tbl_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (osm_mcast_tbl_t*)&p_sw->mcast_tbl );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch.
+*
+* RETURN VALUE
+* Returns a pointer to the switch's multicast table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_is_in_mcast_tree
+* NAME
+* osm_switch_is_in_mcast_tree
+*
+* DESCRIPTION
+* Returns true if this switch already belongs in the tree for the specified
+* multicast group.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_is_in_mcast_tree(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t mlid_ho )
+{
+ const osm_mcast_tbl_t* p_tbl;
+ p_tbl = &p_sw->mcast_tbl;
+ if( p_tbl )
+ return( osm_mcast_tbl_is_any_port( &p_sw->mcast_tbl, mlid_ho ) );
+ else
+ return( FALSE );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch.
+*
+* mlid_ho
+* [in] MLID (host order) of the multicast tree to check.
+*
+* RETURN VALUE
+* Returns true if this switch already belongs in the tree for the specified
+* multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_get
+* NAME
+* osm_switch_discovery_count_get
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_discovery_count_get(
+ IN const osm_switch_t* const p_switch )
+{
+ return( p_switch->discovery_count );
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_switch_discovery_count_reset
+* NAME
+* osm_switch_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this node to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_reset(
+ IN osm_switch_t* const p_switch )
+{
+ p_switch->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+/****f* OpenSM: Node/osm_switch_discovery_count_inc
+* NAME
+* osm_switch_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_inc(
+ IN osm_switch_t* const p_switch )
+{
+ p_switch->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWITCH_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_TRAP_RCV_H_
+#define _OSM_TRAP_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/cl_event_wheel.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Trap Receiver
+* NAME
+* Trap Receiver
+*
+* DESCRIPTION
+* The Trap Receiver object encapsulates the information
+* needed to receive the Trap attribute from a node.
+*
+* The Trap Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Trap Receiver/osm_trap_rcv_t
+* NAME
+* osm_trap_rcv_t
+*
+* DESCRIPTION
+* Trap Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_tap_rcv
+{
+ osm_subn_t *p_subn;
+ osm_stats_t *p_stats;
+ osm_log_t *p_log;
+ osm_resp_t *p_resp;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+ cl_event_wheel_t trap_aging_tracker;
+} osm_trap_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_resp
+* Pointer to the generic MAD responder object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* trap_aging_tracker
+* An event wheel tracking erceived traps and their aging.
+* Basically we can start a timer every time we receive a specific
+* trap and check to seee if not expired next time it is received.
+*
+* SEE ALSO
+* Trap Receiver object
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_construct
+* NAME
+* osm_trap_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Trap Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_construct(
+ IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Trap Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_trap_rcv_init, osm_trap_rcv_destroy
+*
+* Calling osm_trap_rcv_construct is a prerequisite to calling any other
+* method except osm_trap_rcv_init.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_init,
+* osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_destroy
+* NAME
+* osm_trap_rcv_destroy
+*
+* DESCRIPTION
+* The osm_trap_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_destroy(
+ IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Trap Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_trap_rcv_construct or osm_trap_rcv_init.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_construct,
+* osm_trap_rcv_init
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_init
+* NAME
+* osm_trap_rcv_init
+*
+* DESCRIPTION
+* The osm_trap_rcv_init function initializes a
+* Trap Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_trap_rcv_init(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_resp
+* [in] Pointer to the generic MAD Responder object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Trap Receiver methods.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_construct,
+* osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_process
+* NAME
+* osm_trap_rcv_process
+*
+* DESCRIPTION
+* Process the Trap attribute.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_process(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's Trap attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap processing was successful.
+*
+* NOTES
+* This function processes a Trap attribute.
+*
+* SEE ALSO
+* Trap Receiver, Trap Response Controller
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_aging_tracker_callback
+* NAME
+* osm_trap_rcv_aging_tracker_callback
+*
+* DESCRIPTION
+* Callback function called by the aging tracker mechanism.
+*
+* SYNOPSIS
+*/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+ IN uint64_t key,
+ IN uint32_t num_regs,
+ IN void* context );
+
+/*
+* PARAMETERS
+* key
+* [in] The key by which the event was inserted.
+*
+* num_regs
+* [in] The number of times the same event (key) was registered.
+*
+* context
+* [in] Pointer to the context given in the registering of the event.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* This function is called by the cl_event_wheel when the aging tracker event
+* has ended.
+*
+* SEE ALSO
+* Trap Receiver, Trap Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_TRAP_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_trap_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Trap
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_TRAP_RCV_CTRL_H_
+#define _OSM_TRAP_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/***** OpenSM/Trap Receive Controller
+* NAME
+* Trap Receive Controller
+*
+* DESCRIPTION
+* The Trap Receive Controller object encapsulates the information
+* needed to receive the Trap attribute from a node.
+*
+* The Trap Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+/****s* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_t
+* NAME
+* osm_trap_rcv_ctrl_t
+*
+* DESCRIPTION
+* Trap Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_trap_rcv_ctrl
+{
+ osm_trap_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_trap_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Trap Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Trap Receive Controller object
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_construct
+* NAME
+* osm_trap_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Trap Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_construct(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Trap Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_trap_rcv_ctrl_init, osm_trap_rcv_ctrl_destroy
+*
+* Calling osm_trap_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_init,
+* osm_trap_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_destroy
+* NAME
+* osm_trap_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_trap_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_destroy(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Trap Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_trap_rcv_ctrl_construct or osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+* osm_trap_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_init
+* NAME
+* osm_trap_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_trap_rcv_ctrl_init function initializes a
+* Trap Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl,
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_trap_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Trap Receive Controller methods.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+* osm_trap_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_TRAP_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#include "ts_ib_useraccess.h"
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+typedef struct ib_user_mad_filter osm_ts_user_mad_filter;
+typedef struct ib_set_port_info_ioctl osm_ts_set_port_info_ioctl;
+typedef struct ib_get_port_info_ioctl osm_ts_get_port_info_ioctl;
+typedef struct ib_gid_entry_ioctl osm_ts_gid_entry_ioctl;
+
+END_C_DECLS
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ucast_mgr_t.
+ * This object represents the Unicast Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_UCAST_MGR_H_
+#define _OSM_UCAST_MGR_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_UCAST_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/Unicast Manager
+* NAME
+* Unicast Manager
+*
+* DESCRIPTION
+* The Unicast Manager object encapsulates the information
+* needed to control unicast LID forwarding on the subnet.
+*
+* The Unicast Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+/****s* OpenSM: Unicast Manager/osm_ucast_mgr_t
+* NAME
+* osm_ucast_mgr_t
+*
+* DESCRIPTION
+* Unicast Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ucast_mgr
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ char *p_report_buf;
+
+} osm_ucast_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_construct
+* NAME
+* osm_ucast_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Unicast Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_construct(
+ IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Unicast Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_ucast_mgr_destroy
+*
+* Calling osm_ucast_mgr_construct is a prerequisite to calling any other
+* method except osm_ucast_mgr_init.
+*
+* SEE ALSO
+* Unicast Manager object, osm_ucast_mgr_init,
+* osm_ucast_mgr_destroy
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_destroy
+* NAME
+* osm_ucast_mgr_destroy
+*
+* DESCRIPTION
+* The osm_ucast_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_destroy(
+ IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Unicast Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ucast_mgr_construct or osm_ucast_mgr_init.
+*
+* SEE ALSO
+* Unicast Manager object, osm_ucast_mgr_construct,
+* osm_ucast_mgr_init
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_init
+* NAME
+* osm_ucast_mgr_init
+*
+* DESCRIPTION
+* The osm_ucast_mgr_init function initializes a
+* Unicast Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_ucast_mgr_init(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN char* const p_report_buf,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_report_buf
+* [in] Pointer to the large log buffer used for user reporting.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Unicast Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Unicast Manager methods.
+*
+* SEE ALSO
+* Unicast Manager object, osm_ucast_mgr_construct,
+* osm_ucast_mgr_destroy
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_process
+* NAME
+* osm_ucast_mgr_process
+*
+* DESCRIPTION
+* Process and configure the subnet's unicast forwarding tables.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_ucast_mgr_process(
+ IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+* This function processes the subnet, configuring switch
+* unicast forwarding tables.
+*
+* SEE ALSO
+* Unicast Manager, Node Info Response Controller
+*********/
+END_C_DECLS
+
+#endif /* _OSM_UCAST_MGR_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifndef _OSM_UCAST_UPDN_H_
+#define _OSM_UCAST_UPDN_H_
+
+
+/*
+ * Abstract:
+ * Implementation of Up Down Algorithm using ranking & Min Hop
+ * Calculation functions
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+/* LS : This code is useless since we integrate it with opensm */
+/*
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_node.h>
+#include <complib/cl_list.h>
+#include <opensm/osm_subnet.h>
+#include <osmsh/osmsh_ext_ifc.h>
+#include <opensm/osm_ucast_mgr.h>
+*/
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/* //////////////////////////// */
+/* ENUM TypeDefs */
+/* /////////////////////////// */
+
+/*
+* DESCRIPTION
+* This enum respresent available directions of arcs in the graph
+* SYNOPSIS
+*/
+typedef enum _updn_switch_dir
+ {
+ UP = 0,
+ DOWN
+
+ } updn_switch_dir_t;
+
+/*
+ * TYPE DEFINITIONS
+ * UP
+ * Current switch direction in propogating the subnet is up
+ * DOWN
+ * Current switch direction in propogating the subnet is down
+ *
+ */
+
+
+/*
+* DESCRIPTION
+* This enum respresent available states in the UPDN algorithm
+* SYNOPSIS
+*/
+typedef enum _updn_state
+ {
+ UPDN_INIT = 0,
+ UPDN_RANK,
+ UPDN_MIN_HOP_CALC,
+ } updn_state_t;
+
+/*
+ * TYPE DEFINITIONS
+ * UPDN_INIT - loading the package but still not performing anything
+ * UPDN_RANK - post ranking algorithm
+ * UPDN_MIN_HOP_CALC - post min hop table calculation
+ */
+
+
+/* ////////////////////////////////// */
+/* Struct TypeDefs */
+/* ///////////////////////////////// */
+
+/****s* UPDN: Rank element/updn_rank_t
+* NAME
+* updn_rank_t
+*
+* DESCRIPTION
+* This object represents a rank type element in a list
+*
+* The updn_rank_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_rank
+{
+ cl_map_item_t map_item;
+ uint8_t rank;
+} updn_rank_t;
+
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* rank
+* Rank value of this node
+*
+*/
+
+/****s* UPDN: Histogram element/updn_hist_t
+* NAME
+* updn_hist_t
+*
+* DESCRIPTION
+* This object represents a histogram type element in a list
+*
+* The updn_hist_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_hist
+{
+ cl_map_item_t map_item;
+ uint32_t bar_value;
+} updn_hist_t;
+
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* bar_value
+* The number of occurences of the same hop value
+*
+*/
+
+typedef struct _updn_next_step
+{
+ updn_switch_dir_t state;
+ osm_switch_t *p_sw;
+} updn_next_step_t;
+
+/*****s* updn: updn/updn_input_t
+* NAME updn_t
+*
+*
+* DESCRIPTION
+* updn input fields structure.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_input
+{
+ uint32_t num_guids;
+ uint64_t * guid_list;
+} updn_input_t;
+
+/*
+* FIELDS
+* num_guids
+* number of guids given at the UI
+*
+* guid_list
+* guids specified as an array (converted from a list given in the UI)
+*
+*
+* SEE ALSO
+*
+*********/
+
+
+/*****s* updn: updn/updn_t
+* NAME updn_t
+*
+*
+* DESCRIPTION
+* updn structure.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn
+{
+ updn_state_t state;
+ boolean_t auto_detect_root_nodes;
+ cl_qmap_t guid_rank_tbl;
+ updn_input_t updn_ucast_reg_inputs;
+ cl_list_t * p_root_nodes;
+} updn_t;
+
+/*
+* FIELDS
+* state
+* state of the updn algorithm which basically should pass through Init
+* - Ranking - UpDn algorithm
+*
+* guid_rank_tbl
+* guid 2 rank mapping vector , indexed by guid in network order
+*
+*
+* SEE ALSO
+*
+*********/
+
+
+/* ////////////////////////////// */
+/* Function */
+/* ////////////////////////////// */
+
+/***f** Osmsh: Updn/updn_construct
+* NAME
+* updn_construct
+*
+* DESCRIPTION
+* Allocation of updn_t struct
+*
+* SYNOPSIS
+*/
+
+updn_t*
+updn_construct(void);
+
+/*
+* PARAMETERS
+*
+*
+* RETURN VALUE
+* Return a pointer to an updn struct. Null if fails to do so.
+*
+* NOTES
+* First step of the creation of updn_t
+*/
+
+/****s* Osmsh: Updn/updn_destroy
+* NAME
+* updn_destroy
+*
+* DESCRIPTION
+* release of updn_t struct
+*
+* SYNOPSIS
+*/
+
+void
+updn_destroy(
+ IN updn_t* const p_updn );
+
+/*
+* PARAMETERS
+* p_updn
+* A pointer to the updn_t struct that is goining to be released
+*
+* RETURN VALUE
+*
+* NOTES
+* Final step of the releasing of updn_t
+*
+* SEE ALSO
+* updn_construct
+*********/
+
+/****f* Osmsh: Updn/updn_init
+* NAME
+* updn_init
+*
+* DESCRIPTION
+* Initialization of an updn_t struct
+*
+* SYNOPSIS
+*/
+cl_status_t
+updn_init(
+ IN updn_t* const p_updn );
+
+/*
+* PARAMETERS
+* p_updn
+* A pointer to the updn_t struct that is goining to be initilized
+*
+* RETURN VALUE
+* The status of the function.
+*
+* NOTES
+*
+* SEE ALSO
+* updn_construct
+********/
+
+
+
+
+/****** Osmsh: Updn/updn_subn_rank
+* NAME
+* updn_subn_rank
+*
+* DESCRIPTION
+* This function ranks the subnet for credit loop free algorithm
+*
+* SYNOPSIS
+*/
+
+int
+updn_subn_rank(
+ IN uint64_t root_guid ,
+ IN uint8_t base_rank,
+ IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to a Subnet object to construct.
+*
+* base_rank
+* [in] The base ranking value (lowest value)
+*
+* p_updn
+* [in] Pointer to updn structure which includes state & lid2rank table
+*
+* RETURN VALUE
+* This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+
+/****** Osmsh: UpDown/osm_subn_set_up_down_min_hop_table
+* NAME
+* osm_subn_set_up_down_min_hop_table
+*
+* DESCRIPTION
+* This function set min hop table of all switches by BFS through each
+* port guid at the subnet using ranking done before.
+*
+* SYNOPSIS
+*/
+
+int
+osm_subn_set_up_down_min_hop_table(
+ IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+* p_updn
+* [in] Pointer to updn structure which includes state & lid2rank table
+*
+* RETURN VALUE
+* This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+
+
+
+/****** Osmsh: UpDown/osm_subn_calc_up_down_min_hop_table
+* NAME
+* osm_subn_calc_up_down_min_hop_table
+*
+* DESCRIPTION
+* This function perform ranking and setting of all switches' min hop table
+* by UP DOWN algorithm
+*
+* SYNOPSIS
+*/
+
+int
+osm_subn_calc_up_down_min_hop_table(
+ IN uint32_t num_guids,
+ IN uint64_t* guid_list,
+ IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+*
+* guid_list
+* [in] Guid list from which to start ranking .
+*
+* p_updn
+* [in] Pointer to updn structure which includes state & lid2rank table
+* RETURN VALUE
+* This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+/****f* OpenSM: OpenSM/osm_updn_reg_calc_min_hop_table
+* NAME
+* osm_updn_reg_calc_min_hop_table
+*
+* DESCRIPTION
+* Registration function to ucast routing manager (instead of
+* Min Hop Algorithm)
+*
+* SYNOPSIS
+*/
+int
+osm_updn_reg_calc_min_hop_table(
+ IN updn_t * p_updn,
+ IN osm_subn_opt_t* p_opt );
+/*
+* PARAMETERS
+*
+* RETURN VALUES
+* 0 - on success , 1 - on failure
+*
+* NOTES
+*
+* SEE ALSO
+* osm_subn_calc_up_down_min_hop_table
+*********/
+
+/****** Osmsh: UpDown/osm_updn_find_root_nodes_by_min_hop
+* NAME
+* osm_updn_find_root_nodes_by_min_hop
+*
+* DESCRIPTION
+* This function perform auto identification of root nodes for UPDN ranking phase
+*
+* SYNOPSIS
+*/
+int
+osm_updn_find_root_nodes_by_min_hop( OUT updn_t * p_updn );
+
+/*
+* PARAMETERS
+* p_root_nodes_list
+*
+* [out] Pointer to the root nodes list found in the subnet
+*
+* RETURN VALUE
+* This function returns 0 when auto identification had succeeded
+******/
+
+
+END_C_DECLS
+
+#endif /* _OSM_UCAST_UPDN_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mad_wrapper_t.
+ * This object represents the context wrapper for OpenSM MAD processing.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_UMADT_h_
+#define _OSM_UMADT_h_
+
+#include "iba/ib_types.h"
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include "umadt.h"
+#include "ibt.h"
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+typedef struct _umadt_obj_t{
+ void* umadt_handle;
+ UMADT_INTERFACE uMadtInterface;
+ IBT_INTERFACE IbtInterface;
+ boolean init_done;
+ cl_spinlock_t register_lock;
+ cl_qlist_t register_list;
+ osm_log_t *p_log;
+ uint32_t timeout;
+
+}umadt_obj_t;
+/*********/
+/****s* OpenSM: Umadt MAD Wrapper/osm_bind_info
+* NAME
+* osm_bind_info
+*
+* DESCRIPTION
+* Context needed for processing individual MADs
+*
+* SYNOPSIS
+*/
+
+typedef struct _mad_bind_info_t{
+ cl_list_item_t list_item;
+ umadt_obj_t *p_umadt_obj;
+ osm_mad_pool_t *p_mad_pool;
+ osm_vend_mad_recv_callback_t mad_recv_callback;
+ void *client_context;
+ cl_thread_t recv_processor_thread;
+ cl_spinlock_t trans_ctxt_lock;
+ cl_qlist_t trans_ctxt_list;
+ cl_timer_t timeout_timer;
+ cl_spinlock_t timeout_list_lock;
+ cl_qlist_t timeout_list;
+ RegisterClassStruct umadt_reg_class;
+ MADT_HANDLE umadt_handle; /* Umadt type */
+
+}mad_bind_info_t;
+
+typedef struct _trans_context_t {
+ cl_list_item_t list_item;
+ uint64_t trans_id;
+ uint64_t sent_time; /* micro secs */
+ void* context;
+} trans_context_t;
+
+/*
+* FIELDS
+* list_item
+* List linkage for pools and lists. MUST BE FIRST MEMBER!
+*
+* p_mad_pool
+* Pointer to the MAD pool to be used by mads with this bind handle.
+*
+* mad_recv_callback
+* Callback function called by the mad receive processor.
+*
+* client_context
+* context to be passed to the receive callback.
+*
+* recv_processor_thread
+* Thread structure for the receive processor thread.
+*
+* umadt_reg_class
+* Umadt register class struct used to register with Umadt.
+*
+* umadt_handle
+* Umadt returns this handle from a registration call. The transport layer
+* uses this handle to talk to Umadt.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /*_OSM_UMADT_h_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_vl15_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_VL15INTF_H_
+#define _OSM_VL15INTF_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VL15
+* NAME
+* VL15
+*
+* DESCRIPTION
+* The VL15 object encapsulates the information needed by the
+* OpenSM to instantiate the VL15 interface. The OpenSM allocates
+* one VL15 object per subnet.
+*
+* The VL15 object transmits MADs to the wire at a throttled rate,
+* so as to not overload the VL15 buffering of subnet components.
+* OpenSM modules may post VL15 MADs to the VL15 interface as fast
+* as possible.
+*
+* The VL15 object is thread safe.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****d* OpenSM: SM/osm_vl15_state_t
+* NAME
+* osm_vl15_state_t
+*
+* DESCRIPTION
+* Enumerates the possible states of SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_vl15_state
+{
+ OSM_VL15_STATE_INIT = 0,
+ OSM_VL15_STATE_READY
+
+} osm_vl15_state_t;
+/***********/
+
+/****s* OpenSM: VL15/osm_vl15_t
+* NAME
+* osm_vl15_t
+*
+* DESCRIPTION
+* VL15 structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vl15
+{
+ osm_thread_state_t thread_state;
+ osm_vl15_state_t state;
+ uint32_t max_wire_smps;
+ cl_event_t signal;
+ cl_thread_t poller;
+ cl_qlist_t rfifo;
+ cl_qlist_t ufifo;
+ cl_spinlock_t lock;
+ osm_vendor_t *p_vend;
+ osm_log_t *p_log;
+ osm_stats_t *p_stats;
+
+} osm_vl15_t;
+/*
+* FIELDS
+* thread_state
+* Tracks the thread state of the poller thread.
+*
+* state
+* Tracks the state of the VL15 interface itself.
+*
+* max_wire_smps
+* Maximum number of VL15 MADs allowed on the wire at one time.
+*
+* signal
+* Event on which the poller sleeps.
+*
+* rfifo
+* First-in First-out queue for outbound VL15 MADs for which
+* a response is expected, aka the "response fifo"
+*
+* ufifo
+* First-in First-out queue for outbound VL15 MADs for which
+* no response is expected, aka the "unicast fifo".
+*
+* poller
+* Worker thread pool that services the fifo to transmit VL15 MADs
+*
+* lock
+* Spinlock guarding the FIFO.
+*
+* p_vend
+* Pointer to the vendor transport object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* SEE ALSO
+* VL15 object
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_construct
+* NAME
+* osm_vl15_construct
+*
+* DESCRIPTION
+* This function constructs an VL15 object.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_construct(
+ IN osm_vl15_t* const p_vl15 );
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to a VL15 object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vl15_init, osm_vl15_destroy, and osm_vl15_is_inited.
+*
+* Calling osm_vl15_construct is a prerequisite to calling any other
+* method except osm_vl15_init.
+*
+* SEE ALSO
+* VL15 object, osm_vl15_init, osm_vl15_destroy, osm_vl15_is_inited
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_destroy
+* NAME
+* osm_vl15_destroy
+*
+* DESCRIPTION
+* The osm_vl15_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_destroy(
+ IN osm_vl15_t* const p_vl15,
+ IN struct _osm_mad_pool *p_pool);
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to a VL15 object to destroy.
+*
+* p_pool
+* [in] The pointer to the mad pool to return outstanding mads to
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified VL15 object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_vl15_construct or
+* osm_vl15_init.
+*
+* SEE ALSO
+* VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/*
+ Initialization.
+ Rate specifies the minimum number of microseconds between transmissions
+ on VL15.
+*/
+/****f* OpenSM: VL15/osm_vl15_init
+* NAME
+* osm_vl15_init
+*
+* DESCRIPTION
+* The osm_vl15_init function initializes a VL15 object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vl15_init(
+ IN osm_vl15_t* const p_vl15,
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN const int32_t max_wire_smps );
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to an osm_vl15_t object to initialize.
+*
+* p_vend
+* [in] Pointer to the vendor transport object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_stats
+* [in] Pointer to the OpenSM stastics block.
+*
+* max_wire_smps
+* [in] Maximum number of MADs allowed on the wire at one time.
+*
+* RETURN VALUES
+* IB_SUCCESS if the VL15 object was initialized successfully.
+*
+* NOTES
+* Allows calling other VL15 methods.
+*
+* SEE ALSO
+* VL15 object, osm_vl15_construct, osm_vl15_destroy,
+* osm_vl15_is_inited
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_post
+* NAME
+* osm_vl15_post
+*
+* DESCRIPTION
+* Posts a MAD to the VL15 interface for transmission.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_post(
+ IN osm_vl15_t* const p_vl15,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to an osm_vl15_t object.
+*
+* p_madw
+* [in] Pointer to a MAD wrapper structure containing the MAD.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+* The osm_vl15_construct or osm_vl15_init must be called before using
+* this function.
+*
+* SEE ALSO
+* VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_poll
+* NAME
+* osm_vl15_poll
+*
+* DESCRIPTION
+* Causes the VL15 Interface to consider sending another QP0 MAD.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_poll(
+ IN osm_vl15_t* const p_vl );
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to an osm_vl15_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* This function signals the VL15 that it may be possible to send
+* a SMP. This function checks three criteria before sending a SMP:
+* 1) The VL15 worker is IDLE
+* 2) There are no QP0 SMPs currently outstanding
+* 3) There is something on the VL15 FIFO to send
+*
+* SEE ALSO
+* VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_shutdown
+* NAME
+* osm_vl15_shutdown
+*
+* DESCRIPTION
+* Cleanup all outstanding MADs on both fifo's.
+* This is required to return all outstanding MAD resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_shutdown(
+ IN osm_vl15_t* const p_vl,
+ IN osm_mad_pool_t* const p_mad_pool);
+/*
+* PARAMETERS
+* p_vl15
+* [in] Pointer to an osm_vl15_t object.
+*
+* p_mad_pool
+* [in] The MAD pool owning the mads.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VL15INTF_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vla_rcv_t.
+ * This object represents the Vl Arbitration Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_VLA_RCV_H_
+#define _OSM_VLA_RCV_H_
+
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Vl Arbitration Receiver
+* NAME
+* Vl Arbitration Receiver
+*
+* DESCRIPTION
+* The Vl Arbitration Receiver object encapsulates the information
+* needed to set or get the vl arbitration attribute from a port.
+*
+* The Vl Arbitration Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: Vl Arbitration Receiver/osm_vla_rcv_t
+* NAME
+* osm_vla_rcv_t
+*
+* DESCRIPTION
+* Vl Arbitration Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_vla_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Vl Arbitration Receiver object
+*********/
+
+/****f* OpenSM: Vl Arbitration Receiver/osm_vla_rcv_construct
+* NAME
+* osm_vla_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Vl Arbitration Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_construct(
+ IN osm_vla_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Vl Arbitration Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vla_rcv_destroy
+*
+* Calling osm_vla_rcv_construct is a prerequisite to calling any other
+* method except osm_vla_rcv_init.
+*
+* SEE ALSO
+* Vl Arbitration Receiver object, osm_vla_rcv_init,
+* osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: Vl Arbitration Receiver/osm_vla_rcv_destroy
+* NAME
+* osm_vla_rcv_destroy
+*
+* DESCRIPTION
+* The osm_vla_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_destroy(
+ IN osm_vla_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Vl Arbitration Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vla_rcv_construct or osm_vla_rcv_init.
+*
+* SEE ALSO
+* Vl Arbitration Receiver object, osm_vla_rcv_construct,
+* osm_vla_rcv_init
+*********/
+
+/****f* OpenSM: Vl Arbitration Receiver/osm_vla_rcv_init
+* NAME
+* osm_vla_rcv_init
+*
+* DESCRIPTION
+* The osm_vla_rcv_init function initializes a
+* Vl Arbitration Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_init(
+ IN osm_vla_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Vl Arbitration Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Vl Arbitration Receiver methods.
+*
+* SEE ALSO
+* Vl Arbitration Receiver object, osm_vla_rcv_construct,
+* osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: Vl Arbitration Receiver/osm_vla_rcv_process
+* NAME
+* osm_vla_rcv_process
+*
+* DESCRIPTION
+* Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_process(
+ IN const osm_vla_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* Vl Arbitration Receiver, Vl Arbitration Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vla_rcv_ctrl_t.
+ * This object represents a controller that set or get resp the
+ * IBA Vl Arbitration Table attribute from a port.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _OSM_VLA_RCV_CTRL_H_
+#define _OSM_VLA_RCV_CTRL_H_
+
+
+#include <opensm/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl_arb_rcv.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VL Arbitration Table Receive Controller
+* NAME
+* Vl Arbitration Receive Controller
+*
+* DESCRIPTION
+* The VL Arbitration Receive Controller object encapsulates
+* the information needed to get or set VL Arbitration of a port.
+*
+* The VL Arbitration Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+/****s* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_t
+* NAME
+* osm_vla_rcv_ctrl_t
+*
+* DESCRIPTION
+* VL Arbitration Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv_ctrl
+{
+ osm_vla_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_vla_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the VL Arbitration Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object
+* VL Arbitration Receiver object
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_construct
+* NAME
+* osm_vla_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a VL Arbitration Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_construct(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a VL Arbitration Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vla_rcv_ctrl_init, osm_vla_rcv_ctrl_destroy,
+* and osm_vla_rcv_ctrl_is_inited.
+*
+* Calling osm_vla_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_init,
+* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_destroy
+* NAME
+* osm_vla_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_vla_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_destroy(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* VL Arbitration Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_init
+* NAME
+* osm_vla_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_vla_rcv_ctrl_init function initializes a
+* VL Arbitration Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_ctrl_init(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl,
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_vla_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VL Arbitration Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VL Arbitration Receive Controller methods.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_is_inited
+* NAME
+* osm_vla_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_vla_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_vla_rcv_ctrl_is_inited(
+ IN const osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_CTRL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#if (__WORDSIZE == 64) || defined (_WIN64)
+#define st_ptr_t unsigned long long
+#else
+#define st_ptr_t unsigned long
+#endif
+
+typedef st_ptr_t st_data_t;
+
+#define ST_DATA_T_DEFINED
+
+typedef struct st_table st_table;
+
+struct st_hash_type {
+ int (*compare)(void *, void *);
+ st_ptr_t (*hash)(void *);
+};
+
+struct st_table {
+ struct st_hash_type *type;
+ int num_bins;
+ int num_entries;
+ struct st_table_entry **bins;
+};
+
+#define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0)
+
+enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
+
+st_table *st_init_table(struct st_hash_type *);
+st_table *st_init_table_with_size(struct st_hash_type *, int);
+st_table *st_init_numtable(void);
+st_table *st_init_numtable_with_size(int);
+st_table *st_init_strtable(void);
+st_table *st_init_strtable_with_size(int);
+int st_delete(st_table *, st_data_t *, st_data_t *);
+int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t);
+int st_insert(st_table *, st_data_t, st_data_t);
+int st_lookup(st_table *, st_data_t, st_data_t *);
+void st_foreach(st_table *, int (*)(st_data_t key, st_data_t val, st_data_t arg), st_data_t);
+void st_add_direct(st_table *, st_data_t, st_data_t);
+void st_free_table(st_table *);
+void st_cleanup_safe(st_table *, st_data_t);
+st_table *st_copy(st_table *);
+
+#define ST_NUMCMP ((int (*)()) 0)
+#define ST_NUMHASH ((int (*)()) -2)
+
+#define st_numcmp ST_NUMCMP
+#define st_numhash ST_NUMHASH
+
+/* int st_strhash(void); */
+
+END_C_DECLS
+
+#endif /* ST_INCLUDED */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Include file used by OpenSM to pull in the correct vendor file.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+ this is the generic include file which includes
+ the proper vendor specific file
+*/
+#include <vendor/osm_vendor_select.h>
+
+#if defined( OSM_VENDOR_INTF_TEST )
+#include <vendor/osm_vendor_test.h>
+#elif defined( OSM_VENDOR_INTF_UMADT )
+#include <vendor/osm_vendor_umadt.h>
+#elif defined( OSM_VENDOR_INTF_MTL )
+/* HACK - I do not know how to prevent complib from loading kernel H files */
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_TS )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_ANAFA )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_SIM )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_OPENIB )
+#include <vendor/osm_vendor_ibumad.h>
+#elif defined( OSM_VENDOR_INTF_AL )
+#include <vendor/osm_vendor_al.h>
+#elif
+#error No MAD Interface selected!
+#error Choose an interface in osm_vendor_select.h
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mad_wrapper_t.
+ * This object represents the context wrapper for OpenSM MAD processing.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+
+
+#ifndef _OSM_VENDOR_AL_H_
+#define _OSM_VENDOR_AL_H_
+
+#include <iba/ib_types.h>
+#include <iba/ib_al.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Vendor AL
+* NAME
+* Vendor AL
+*
+* DESCRIPTION
+*
+* The Vendor AL object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* Enable various hacks to compensate for bugs in external code...
+*
+*
+* AUTHOR
+*
+*
+*********/
+
+
+
+/****h* OpenSM/Vendor Access Layer (AL)
+* NAME
+* Vendor AL
+*
+* DESCRIPTION
+* This file is the vendor specific file for the AL Infiniband API.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+#define OSM_AL_SQ_SGE 256
+#define OSM_AL_RQ_SGE 256
+#define OSM_DEFAULT_RETRY_COUNT 3
+
+/* AL supports RMPP */
+#define VENDOR_RMPP_SUPPORT 1
+
+/****s* OpenSM: Vendor AL/osm_ca_info_t
+* NAME
+* osm_ca_info_t
+*
+* DESCRIPTION
+* Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info
+{
+ ib_net64_t guid;
+ uint32_t attr_size;
+ ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+/*
+* FIELDS
+* guid
+* Node GUID of the local CA.
+*
+* attr_size
+* Size of the CA attributes for this CA.
+*
+* p_attr
+* Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports
+* NAME
+* osm_ca_info_get_num_ports
+*
+* DESCRIPTION
+* Returns the number of ports owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_num_ports(
+ IN const osm_ca_info_t* const p_ca_info )
+{
+ return( p_ca_info->p_attr->num_ports );
+}
+/*
+* PARAMETERS
+* p_ca_info
+* [in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+* Returns the number of ports owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid
+* NAME
+* osm_ca_info_get_port_guid
+*
+* DESCRIPTION
+* Returns the port GUID of the specified port owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_port_guid(
+ IN const osm_ca_info_t* const p_ca_info,
+ IN const uint8_t index )
+{
+ return( p_ca_info->p_attr->p_port_attr[index].port_guid );
+}
+/*
+* PARAMETERS
+* p_ca_info
+* [in] Pointer to a CA Info object.
+*
+* index
+* [in] Port "index" for which to retrieve the port GUID.
+* The index is the offset into the ca's internal array
+* of port attributes.
+*
+* RETURN VALUE
+* Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_num
+* NAME
+* osm_ca_info_get_port_num
+*
+* DESCRIPTION
+* Returns the port number of the specified port owned by this CA.
+* Port numbers start with 1 for HCA's.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_port_num(
+ IN const osm_ca_info_t* const p_ca_info,
+ IN const uint8_t index )
+{
+ return( p_ca_info->p_attr->p_port_attr[index].port_num );
+}
+/*
+* PARAMETERS
+* p_ca_info
+* [in] Pointer to a CA Info object.
+*
+* index
+* [in] Port "index" for which to retrieve the port GUID.
+* The index is the offset into the ca's internal array
+* of port attributes.
+*
+* RETURN VALUE
+* Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_ca_guid
+* NAME
+* osm_ca_info_get_ca_guid
+*
+* DESCRIPTION
+* Returns the GUID of the specified CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_ca_guid(
+ IN const osm_ca_info_t* const p_ca_info )
+{
+ return( p_ca_info->p_attr->ca_guid );
+}
+/*
+* PARAMETERS
+* p_ca_info
+* [in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+* Returns the GUID of the specified CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+* osm_bind_handle_t
+*
+* DESCRIPTION
+* handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor
+{
+ ib_al_handle_t h_al;
+ osm_log_t *p_log;
+ size_t ca_count;
+ osm_ca_info_t *p_ca_info;
+ uint32_t timeout;
+ ib_ca_handle_t h_ca;
+ ib_pd_handle_t h_pd;
+
+} osm_vendor_t;
+/*
+* FIELDS
+* h_al
+* Handle returned by AL open call (ib_open_al).
+*
+* p_log
+* Pointer to the log object.
+*
+* ca_count
+* Number of CA's in the array pointed to by p_ca_info.
+*
+* p_ca_info
+* Pointer to dynamically allocated array of CA info objects.
+*
+* h_pool
+* MAD Pool handle returned by ib_create_mad_pool at init time.
+*
+* timeout
+* Transaction timeout time in milliseconds.
+*
+* SEE ALSO
+*********/
+
+
+#ifndef OSM_BIND_INVALID_HANDLE
+#define OSM_BIND_INVALID_HANDLE NULL
+#endif
+
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+* osm_bind_handle_t
+*
+* DESCRIPTION
+* handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef void* osm_bind_handle_t;
+/***********/
+
+/****s* OpenSM/osm_vend_wrap_t
+* NAME
+* AL Vendor MAD Wrapper
+*
+* DESCRIPTION
+* AL specific MAD wrapper. AL transport layer uses this for
+* housekeeping.
+*
+* SYNOPSIS
+*********/
+typedef struct _osm_vend_wrap_t
+{
+ uint32_t size;
+ osm_bind_handle_t h_bind;
+ ib_mad_element_t *p_elem;
+ ib_av_handle_t h_av;
+ void* p_resp_madw;
+
+}osm_vend_wrap_t;
+/*
+* FIELDS
+* size
+* Size of the allocated MAD
+*
+* h_bind
+* Bind handle used on this transaction
+*
+* p_elem
+* Pointer to the mad element structure associated with
+* this mad.
+*
+* h_av
+* Address vector handle used for this transaction.
+*
+* p_resp_madw
+* Pointer to the mad wrapper structure used to hold the pending
+* reponse to the mad, if any. If a response is expected, the
+* wrapper for the reponse is allocated during the send call.
+*
+* SEE ALSO
+*********/
+
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_AL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Specification of the OpenSM transport API. This API is OpenSM's view
+ * of the Infiniband transport.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_API_H_
+#define _OSM_VENDOR_API_H_
+
+
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM Vendor API/osm_vend_mad_recv_callback_t
+* NAME
+* osm_vend_mad_recv_callback_t
+*
+* DESCRIPTION
+* Function prototype for the vendor MAD receive callback.
+* The vendor layer calls this function for MAD receives.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_vend_mad_recv_callback_t)(
+ IN osm_madw_t *p_madw,
+ IN void* bind_context,
+ IN osm_madw_t *p_req_madw );
+/*
+* PARAMETERS
+* p_madw
+* [in] The received MAD wrapper.
+*
+* bind_context
+* [in] User context supplied during the bind call.
+*
+* p_req_madw
+* [in] Pointer to the request mad wrapper that generated this response.
+* If the inbound MAD is not a response, this field is NULL.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM Vendor API/osm_vend_mad_send_err_callback_t
+* NAME
+* osm_vend_mad_send_err_callback_t
+*
+* DESCRIPTION
+* Function prototype for the vendor send failure callback.
+* The vendor layer calls this function when MADs expecting
+* a response are completed in error, most likely due to a
+* timeout.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_vend_mad_send_err_callback_t)(
+ IN void* bind_context,
+ IN osm_madw_t *p_madw );
+/*
+* PARAMETERS
+* bind_context
+* [in] User context supplied during the bind call.
+*
+* p_madw
+* [in] Pointer to the request mad that failed.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* The vendor layer does not call this function (or any other)
+* for MADs that were not expecting a response.
+*
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM Vendor API/osm_vendor_new
+* NAME
+* osm_vendor_new
+*
+* DESCRIPTION
+* Allocates and initializes a new osm_vendor_t object.
+* OpenSM calls this function before any other in the vendor API.
+* This object is passed as a parameter to all other vendor functions.
+*
+* SYNOPSIS
+*/
+osm_vendor_t*
+osm_vendor_new(
+ IN osm_log_t* const p_log,
+ IN const uint32_t timeout );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object to use.
+*
+* timeout
+* [in] transaction timeout
+*
+* RETURN VALUES
+* Returns a pointer to the vendor object.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM Vendor API/osm_vendor_delete
+* NAME
+* osm_vendor_delete
+*
+* DESCRIPTION
+* Dealocate the vendor object.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_delete(
+ IN osm_vendor_t** const pp_vend );
+/*
+* PARAMETERS
+* pp_vend
+* [in/out] pointer to pointer to vendor objcet to be deleted
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_get_ports
+* NAME
+* osm_vendor_get_ports
+*
+* DESCRIPTION
+* Returns an array of available port attribute structures.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_get_all_port_attr(
+ IN osm_vendor_t* const p_vend,
+ IN ib_port_attr_t* const p_attr_array,
+ IN uint32_t* const p_num_ports );
+/*
+* PARAMETERS
+* p_vend
+* [in] Pointer to the vendor object to initialize.
+*
+* p_attr_array
+* [in/out] Pointer to pre-allocated array of port attributes.
+* If it is NULL - then the command only updates the p_num_ports,
+* and return IB_INSUFFICIENT_MEMORY.
+*
+* p_num_ports
+* [in/out] Pointer to a variable to hold the total number of ports
+* available on the local machine..
+*
+* RETURN VALUES
+* IB_SUCCESS on success.
+* IB_INSUFFICIENT_MEMORY if the attribute array was not large enough.
+* The number of attributes needed is returned in num_guids.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_init
+* NAME
+* osm_vendor_init
+*
+* DESCRIPTION
+* The osm_vendor_init function initializes the vendor transport layer.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_init(
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t * const p_log,
+ IN const uint32_t timeout
+ );
+/*
+* PARAMETERS
+* p_vend
+* [in] Pointer to the vendor object to initialize.
+*
+* p_log
+* [in] Pointer to OpenSM's log object. Vendor code may
+* use the log object to send messages to OpenSM's log.
+*
+* timeout
+* [in] Transaction timeout value in milliseconds.
+* A value of 0 disables timeouts.
+*
+*
+* RETURN VALUE
+*
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM Vendor API/osm_vendor_bind
+* NAME
+* osm_vendor_bind
+*
+* DESCRIPTION
+* The osm_vendor_bind function registers with the vendor transport layer
+* per Mad Class per PortGuid for mad transport capability.
+*
+* SYNOPSIS
+*/
+osm_bind_handle_t
+osm_vendor_bind(
+ IN osm_vendor_t* const p_vend,
+ IN osm_bind_info_t* const p_bind_info,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vend_mad_recv_callback_t mad_recv_callback,
+ IN osm_vend_mad_send_err_callback_t send_err_callback,
+ IN void* context );
+/*
+* PARAMETERS
+* p_vend
+* [in] pointer to the vendor object
+*
+* p_osm_bind_info
+* [in] pointer to a struct defining the type of bind to perform.
+*
+* p_mad_pool
+* [in] pointer to a mad wrappers pool to be used for allocating
+* mad wrappers on send and receive.
+*
+* mad_recv_callback
+* [in] the callback function to be invoked on mad receive.
+*
+* send_err_callback
+* [in] the callback function to be invoked on mad transaction errors.
+*
+* context
+* [in] the context to be provided to the callbacks as bind_ctx.
+*
+* RETURN VALUE
+* On success, a valid bind handle.
+* OSM_BIND_INVALID_HANDLE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_unbind
+* NAME
+* osm_vendor_unbind
+*
+* DESCRIPTION
+* Unbind the given bind handle (obtained by osm_vendor_bind).
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_unbind(
+ IN osm_bind_handle_t h_bind);
+/*
+* PARAMETERS
+* h_bind
+* [in] the bind handle to release.
+*
+* RETURN VALUE
+* NONE.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM Vendor API/osm_vendor_get
+* NAME
+* osm_vendor_get
+*
+* DESCRIPTION
+* Obtain a mad wrapper holding actual mad buffer to be sent via
+* the transport.
+*
+* SYNOPSIS
+*/
+ib_mad_t*
+osm_vendor_get(
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t mad_size,
+ IN osm_vend_wrap_t* const p_vend_wrap );
+/*
+* PARAMETERS
+* h_bind
+* [in] the bind handle obtained by calling osm_vendor_bind
+*
+* mad_size
+* [in] the actual mad size required
+*
+* p_vend_wrap
+* [out] the returned mad vendor wrapper
+*
+* RETURN VALUE
+* IB_SUCCESS on succesful completion.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_send
+* NAME
+* osm_vendor_send
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_send(
+ IN osm_bind_handle_t h_bind,
+ IN osm_madw_t* const p_madw,
+ IN boolean_t const resp_expected);
+/*
+* PARAMETERS
+* h_bind
+* [in] the bind handle obtained by calling osm_vendor_bind
+*
+* p_madw
+* [in] pointer to the Mad Wrapper structure for the MAD to be sent.
+*
+* resp_expected
+* [in] boolean value declaring the mad as a request (expecting a response).
+*
+* RETURN VALUE
+* IB_SUCCESS on succesful completion.
+*
+*
+* NOTES
+* 1. Only mads that expect a response are tracked for transaction competion.
+* 2. A mad that does not expect a response is being put back immediatly after
+* being sent.
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM Vendor API/osm_vendor_put
+* NAME
+* osm_vendor_put
+*
+* DESCRIPTION
+* Return a mad vandor wrapper to the mad pool. It also means that the
+* mad buffer is returned to the transport.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_put(
+ IN osm_bind_handle_t h_bind,
+ IN osm_vend_wrap_t* const p_vend_wrap );
+/*
+* PARAMETERS
+* h_bind
+* [in] the bind handle obtained by calling osm_vendor_bind
+*
+* p_vend_wrap
+* [in] pointer to the mad vendor wrapper to put back into the pool.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****i* OpenSM Vendor API/osm_vendor_local_lid_change
+* NAME
+* osm_vendor_local_lid_change
+*
+* DESCRIPTION
+* Notifies the vendor transport layer that the local address
+* has changed. This allows the vendor layer to perform housekeeping
+* functions such as address vector updates.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_local_lid_change(
+ IN osm_bind_handle_t h_bind );
+/*
+* PARAMETERS
+* h_bind
+* [in] the bind handle obtained by calling osm_vendor_bind
+*
+* RETURN VALUE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_sm
+* NAME
+* osm_vendor_set_sm
+*
+* DESCRIPTION
+* Modifies the port info for the bound port to set the "IS_SM" bit
+* according to the value given (TRUE or FALSE).
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_set_sm(
+ IN osm_bind_handle_t h_bind,
+ IN boolean_t is_sm_val );
+/*
+* PARAMETERS
+* h_bind
+* [in] bind handle for this port.
+*
+* is_sm_val
+* [in] If TRUE - will set the is_sm to TRUE, if FALSE - will set the
+* the is_sm to FALSE.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_debug
+* NAME
+* osm_vendor_set_debug
+*
+* DESCRIPTION
+* Modifies the vendor specific debug level.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_set_debug(
+ IN osm_vendor_t* const p_vend,
+ IN int32_t level );
+/*
+* PARAMETERS
+* p_vend
+* [in] vendor handle.
+*
+* level
+* [in] vendor specific debug level.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_API_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Specification of the OpenSM SA API. This API uses the basic osm vendor
+ * API to provide SA Client interface.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_SA_API_H_
+#define _OSM_VENDOR_SA_API_H_
+
+#include <iba/ib_types.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****d* OpenSM Vendor SA Client/osmv_flags_t
+* NAME
+* osmv_flags_t
+*
+* DESCRIPTION
+* Access layer flags used to direct the operation of various calls.
+*
+* SYNOPSIS
+*/
+typedef uint32_t osmv_flags_t;
+#define OSM_SA_FLAGS_SYNC 0x00000001
+/*
+* VALUES
+* OSM_SA_FLAGS_SYNC
+* Indicates that the given operation should be performed synchronously.
+* The call will block until it completes. Callbacks will still be
+* invoked.
+*
+* SEE ALSO
+* osmv_query_sa
+*****/
+
+/****d* OpenSM Vendor SA Client/osmv_query_type_t
+* NAME
+* osmv_query_type_t
+*
+* DESCRIPTION
+* Abstracted queries supported by the access layer.
+*
+* SYNOPSIS
+*/
+typedef enum _osmv_query_type
+{
+ OSMV_QUERY_USER_DEFINED,
+
+ OSMV_QUERY_ALL_SVC_RECS,
+ OSMV_QUERY_SVC_REC_BY_NAME,
+ OSMV_QUERY_SVC_REC_BY_ID,
+
+ OSMV_QUERY_CLASS_PORT_INFO,
+
+ OSMV_QUERY_NODE_REC_BY_NODE_GUID,
+ OSMV_QUERY_PORT_REC_BY_LID,
+ OSMV_QUERY_PORT_REC_BY_LID_AND_NUM,
+
+ OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK,
+ OSMV_QUERY_SLVL_BY_LID_AND_PORTS,
+
+ OSMV_QUERY_PATH_REC_BY_PORT_GUIDS,
+ OSMV_QUERY_PATH_REC_BY_GIDS,
+ OSMV_QUERY_PATH_REC_BY_LIDS,
+
+ OSMV_QUERY_UD_MULTICAST_SET,
+ OSMV_QUERY_UD_MULTICAST_DELETE
+
+} osmv_query_type_t;
+/*
+* VALUES
+* OSMV_QUERY_USER_DEFINED
+* Query the SA based on user-defined input. Queries of this type
+* should reference an osmv_user_query_t structure as input into the
+* query.
+*
+* OSMV_QUERY_SVC_REC_BY_NAME
+* Query for service records based on the service name. Queries of
+* this type should reference an ib_svc_name_t structure as input
+* into the query.
+*
+* OSMV_QUERY_SVC_REC_BY_ID
+* Query for service records based on the service ID. Queries of
+* this type should reference an ib_net64_t value that indicates the
+* ID of the service being requested.
+*
+* OSMV_QUERY_NODE_REC_BY_NODE_GUID
+* Query for node information based on the node's GUID. Queries of
+* this type should reference an ib_net64_t value that indicates the
+* GUID of the node being requested.
+*
+* OSMV_QUERY_PORT_REC_BY_LID
+* Query for port information based on the port's base LID. Queries of
+* this type should reference an ib_net16_t value that indicates the
+* base LID of the port being requested.
+*
+* OSMV_QUERY_PORT_REC_BY_LID_AND_NUM
+* Query for port information based on the port's LID and port num.
+* Queries of this type should reference an osmv_user_query_t
+* structure as input into the query. The port num and lid should
+* be provided by it.
+*
+* OSMV_QUERY_PATH_REC_BY_PORT_GUIDS
+* Query for path records between the specified pair of port GUIDs.
+* Queries of this type should reference an osmv_guid_pair_t structure
+* that indicates the GUIDs of the path being requested.
+*
+* OSMV_QUERY_PATH_REC_BY_GIDS
+* Query for path records between the specified pair of port GIDs.
+* Queries of this type should reference an osmv_gid_pair_t structure
+* that indicates the GIDs of the path being requested.
+*
+* OSMV_QUERY_PATH_REC_BY_LIDS
+* Query for path records between the specified pair of port LIDs.
+* Queries of this type should reference an osmv_lid_pair_t structure
+* that indicates the LIDs of the path being requested.
+*
+* NOTES
+* This enum is used to define abstracted queries provided by the access
+* layer. Users may issue queries not listed here by sending MADs directly
+* to the subnet administrator or a class manager. These queries are
+* intended to represent those most often used by clients.
+*
+* SEE ALSO
+* osmv_query, osmv_query_req_t, osmv_user_query_t, osmv_gid_pair_t,
+* osmv_lid_pair_t osmv_guid_pair_t
+*****/
+
+
+/****s* OpenSM Vendor SA Client/osmv_user_query_t
+* NAME
+* osmv_user_query_t
+*
+* DESCRIPTION
+* User-defined query information.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_user_query
+{
+ uint8_t method;
+ ib_net16_t attr_id;
+ ib_net16_t attr_offset;
+ ib_net64_t comp_mask;
+ void *p_attr;
+
+} osmv_user_query_t;
+/*
+* FIELDS
+*
+* method
+* Method to be run
+*
+* attr_id
+* Attribute identifier of query data.
+*
+* attr_offset
+* Size of the query attribute, in 8-byte words. Users can set this
+* value by passing in the sizeof( attribute ) into the
+* ib_get_attr_offset() routine.
+*
+* comp_mask
+* Indicates the attribute components that are specified for the query.
+*
+* p_attr
+* References the attribute structure used as input into the query.
+* This field is ignored if comp_mask is set to 0.
+*
+* NOTES
+* This structure is used to describe a user-defined query. The attribute
+* ID, attribute offset, component mask, and attribute structure must match
+* those defined by the IBA specification. Users should refer to chapter 15
+* of the IBA specification for additional details.
+*
+* SEE ALSO
+* osmv_query_type_t, ib_get_attr_offset, ib_get_attr_size, osmv_query_sa
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_gid_pair_t
+* NAME
+* osmv_gid_pair_t
+*
+* DESCRIPTION
+* Source and destination GIDs.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_gid_pair
+{
+ ib_gid_t src_gid;
+ ib_gid_t dest_gid;
+
+} osmv_gid_pair_t;
+/*
+* FIELDS
+* src_gid
+* Source GID of a path.
+*
+* dest_gid
+* Destination GID of a path.
+*
+* NOTES
+* This structure is used to describe the endpoints of a path.
+*
+* SEE ALSO
+* ib_gid_t
+*****/
+
+
+/****s* OpenSM Vendor SA Client/osmv_lid_pair_t
+* NAME
+* osmv_lid_pair_t
+*
+* DESCRIPTION
+* Source and destination LIDs.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_lid_pair
+{
+ ib_net16_t src_lid;
+ ib_net16_t dest_lid;
+
+} osmv_lid_pair_t;
+/*
+* FIELDS
+* src_lid
+* Source LID of a path.
+*
+* dest_lid
+* Destination LID of a path.
+*
+* NOTES
+* This structure is used to describe the endpoints of a path.
+*****/
+
+
+/****s* OpenSM Vendor SA Client/osmv_guid_pair_t
+* NAME
+* osmv_guid_pair_t
+*
+* DESCRIPTION
+* Source and destination GUIDs. These may be port or channel adapter
+* GUIDs, depending on the context in which this structure is used.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_guid_pair
+{
+ ib_net64_t src_guid;
+ ib_net64_t dest_guid;
+
+} osmv_guid_pair_t;
+/*
+* FIELDS
+* src_guid
+* Source GUID of a path.
+*
+* dest_guid
+* Destination GUID of a path.
+*
+* NOTES
+* This structure is used to describe the endpoints of a path. The given
+* GUID pair may belong to either ports or channel adapters.
+*
+* SEE ALSO
+* ib_guid_t
+*****/
+
+
+/****s* OpenSM Vendor SA Client/osmv_query_res_t
+* NAME
+* osmv_query_res_t
+*
+* DESCRIPTION
+* Contains the results of a subnet administration query.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_query_res
+{
+ const void *query_context;
+ ib_api_status_t status;
+ osmv_query_type_t query_type;
+ uint32_t result_cnt;
+ osm_madw_t *p_result_madw;
+
+} osmv_query_res_t;
+/*
+* FIELDS
+* query_context
+* User-defined context information associated with the query through
+* the osm_vendor_query_sa call.
+*
+* status
+* Indicates the success of the query operation.
+*
+* query_type
+* Indicates the type of query for which the results are being returned.
+* This matches the query_type specified through the osm_vendor_query_sa
+* call.
+*
+* result_cnt
+* The number of result structures that were returned by the query.
+*
+* p_result_madw
+* For queries returning IB_SUCCESS or IB_REMOTE_ERROR, this references
+* the MAD wrapper returned by the subnet administrator containing the list
+* of results or the returned error code.
+*
+* NOTES
+* A query result structure is returned to a client through their
+* osmv_pfn_query_cb_t routine to notify them of the results of a subnet
+* administration query. If the query was successful or received an error
+* from the subnet administrator, p_result_madw will reference a MAD wrapper
+* containing the results. The MAD referenced by p_result_madw is owned by
+* the user and remains available even after their callback returns. Users
+* must call osm_mad_pool_put() to return the MAD wrapper back to the
+* mad pool when they are done accessing the results.
+*
+* To retrieve individual result structures from the p_result_madw, users
+* may call osmv_get_query_result().
+*
+* SEE ALSO
+* osmv_query_sa, osmv_pfn_query_cb_t, ib_api_status_t,
+* osmv_query_status_t, osmv_query_type_t,
+* osmv_get_query_result
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_result
+* NAME
+* osmv_get_query_result
+*
+* DESCRIPTION
+* Retrieves a result structure from a MADW returned by a call to
+* osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline void*
+osmv_get_query_result(
+ IN osm_madw_t *p_result_madw,
+ IN uint32_t result_index )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ CL_ASSERT( p_result_madw );
+ p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+ CL_ASSERT( p_sa_mad );
+ CL_ASSERT( ib_get_attr_size( p_sa_mad->attr_offset ) * (result_index + 1) +
+ IB_SA_MAD_HDR_SIZE <= p_result_madw->mad_size );
+
+ return( p_sa_mad->data +
+ (ib_get_attr_size( p_sa_mad->attr_offset ) * result_index) );
+}
+/*
+* PARAMETERS
+* p_result_madw
+* [in] This is a reference to the MAD returned as a result of the
+* query.
+*
+* result_index
+* [in] A zero-based index indicating which result to return.
+*
+* NOTES
+* This call returns a pointer to the start of a result structure from a call
+* to osmv_query_sa(). The type of result structure must be known to the user
+* either through the user's context or the query_type returned as part of
+* the osmv_query_res_t structure.
+*
+* SEE ALSO
+* osmv_query_res_t, osm_madw_t
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_path_rec
+* NAME
+* osmv_get_query_path_rec
+*
+* DESCRIPTION
+* Retrieves a path record result from a MAD returned by a call to
+* osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_path_rec_t*
+osmv_get_query_path_rec(
+ IN osm_madw_t *p_result_madw,
+ IN uint32_t result_index )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ CL_ASSERT( p_result_madw );
+ p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+ CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD );
+
+ return( (ib_path_rec_t*)osmv_get_query_result( p_result_madw, result_index ) );
+}
+/*
+* PARAMETERS
+* p_result_madw
+* [in] This is a reference to the MAD returned as a result of the
+* query.
+*
+* result_index
+* [in] A zero-based index indicating which result to return.
+*
+* NOTES
+* This call returns a pointer to the start of a path record result from
+* a call to osmv_query_sa().
+*
+* SEE ALSO
+* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_path_rec_t
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_portinfo_rec
+* NAME
+* osmv_get_query_portinfo_rec
+*
+* DESCRIPTION
+* Retrieves a port info record result from a MAD returned by a call to
+* osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_portinfo_record_t*
+osmv_get_query_portinfo_rec(
+ IN osm_madw_t *p_result_madw,
+ IN uint32_t result_index )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ CL_ASSERT( p_result_madw );
+ p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+ CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD );
+
+ return( (ib_portinfo_record_t*)osmv_get_query_result( p_result_madw,
+ result_index ) );
+}
+/*
+* PARAMETERS
+* p_result_madw
+* [in] This is a reference to the MAD returned as a result of the
+* query.
+*
+* result_index
+* [in] A zero-based index indicating which result to return.
+*
+* NOTES
+* This call returns a pointer to the start of a port info record result from
+* a call to osmv_query_sa().
+*
+* SEE ALSO
+* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_portinfo_record_t
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_node_rec
+* NAME
+* osmv_get_query_node_rec
+*
+* DESCRIPTION
+* Retrieves a node record result from a MAD returned by a call to
+* osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_node_record_t*
+osmv_get_query_node_rec(
+ IN osm_madw_t *p_result_madw,
+ IN uint32_t result_index )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ CL_ASSERT( p_result_madw );
+ p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+ CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_NODE_RECORD );
+
+ return( (ib_node_record_t*)osmv_get_query_result( p_result_madw,
+ result_index ) );
+}
+/*
+* PARAMETERS
+* p_result_madw
+* [in] This is a reference to the MAD returned as a result of the
+* query.
+*
+* result_index
+* [in] A zero-based index indicating which result to return.
+*
+* NOTES
+* This call returns a pointer to the start of a node record result from
+* a call to osmv_query_sa().
+*
+* SEE ALSO
+* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_node_record_t
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_svc_rec
+* NAME
+* osmv_get_query_svc_rec
+*
+* DESCRIPTION
+* Retrieves a service record result from a MAD returned by a call to
+* osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_service_record_t*
+osmv_get_query_svc_rec(
+ IN osm_madw_t *p_result_madw,
+ IN uint32_t result_index )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ CL_ASSERT( p_result_madw );
+ p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+ CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD );
+
+ return( (ib_service_record_t*)osmv_get_query_result( p_result_madw,
+ result_index ) );
+}
+/*
+* PARAMETERS
+* p_result_madw
+* [in] This is a reference to the MAD returned as a result of the
+* query.
+*
+* result_index
+* [in] A zero-based index indicating which result to return.
+*
+* NOTES
+* This call returns a pointer to the start of a service record result from
+* a call to osmv_query_sa().
+*
+* SEE ALSO
+* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_service_record_t
+*****/
+
+
+/****f* OpenSM Vendor SA Client/osmv_pfn_query_cb_t
+* NAME
+* osmv_pfn_query_cb_t
+*
+* DESCRIPTION
+* User-defined callback invoked on completion of a subnet administrator
+* query.
+*
+* SYNOPSIS
+*/
+typedef void
+(*osmv_pfn_query_cb_t)(
+ IN osmv_query_res_t *p_query_res );
+/*
+* PARAMETERS
+* p_query_res
+* [in] This is a reference to a structure containing the result of the
+* query.
+*
+* NOTES
+* This routine is invoked to notify a client of the result of a subnet
+* administration query. The p_query_rec parameter references the result
+* of the query and, in the case of a successful query, any information
+* returned by the subnet administrator.
+*
+* In the kernel, this callback is usually invoked using a tasklet, dependent
+* on the implementation of the underlying verbs provider driver.
+*
+* SEE ALSO
+* osmv_query_res_t
+*****/
+
+
+/****s* OpenSM Vendor SA Client/osmv_query_req_t
+* NAME
+* osmv_query_req_t
+*
+* DESCRIPTION
+* Information used to request an access layer provided query of the subnet
+* administrator.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_query_req
+{
+ osmv_query_type_t query_type;
+ const void *p_query_input;
+ ib_net64_t sm_key;
+
+ uint32_t timeout_ms;
+ uint32_t retry_cnt;
+ osmv_flags_t flags;
+
+ const void *query_context;
+ osmv_pfn_query_cb_t pfn_query_cb;
+
+} osmv_query_req_t;
+/*
+* FIELDS
+* query_type
+* Indicates the type of query that the access layer should perform.
+*
+* p_query_input
+* A pointer to the input for the query. The data referenced by this
+* structure is dependent on the type of query being requested and is
+* determined by the specified query_type.
+*
+* sm_key
+* The M_Key to be provided with the SA MAD for authentication.
+* Normally 0 is used.
+*
+* timeout_ms
+* Specifies the number of milliseconds to wait for a response for
+* this query until retrying or timing out the request.
+*
+* retry_cnt
+* Specifies the number of times that the query will be retried before
+* failing the request.
+*
+* flags
+* Used to describe the mode of operation. Set to IB_FLAGS_SYNC to
+* process the called routine synchronously.
+*
+* query_context
+* User-defined context information associated with this query. The
+* context data is returned to the user as a part of their query
+* callback.
+*
+* pfn_query_cb
+* A user-defined callback that is invoked upon completion of the query.
+*
+* NOTES
+* This structure is used when requesting an osm vendor provided query
+* of the subnet administrator. Clients specify the type of query through
+* the query_type field. Based on the type of query, the p_query_input
+* field is set to reference the appropriate data structure.
+*
+* The information referenced by the p_query_input field is one of the
+* following:
+*
+* -- a NULL terminated service name
+* -- a service id
+* -- a single GUID
+* -- a pair of GUIDs specified through an osmv_guid_pair_t structure
+* -- a pair of GIDs specified through an osmv_gid_pair_t structure
+*
+* SEE ALSO
+* osmv_query_type_t, osmv_pfn_query_cb_t, osmv_guid_pair_t,
+* osmv_gid_pair_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_bind_sa
+* NAME
+* osmv_bind_sa
+*
+* DESCRIPTION
+* Bind to the SA service and return a handle to be used for later
+* queries.
+*
+*
+* SYNOPSIS
+*/
+osm_bind_handle_t
+osmv_bind_sa(
+ IN osm_vendor_t * const p_vend,
+ IN osm_mad_pool_t * const p_mad_pool,
+ IN ib_net64_t port_guid
+ );
+/*
+* PARAMETERS
+* p_vend
+* [in] an osm_vendor object to work with
+*
+* p_mad_pool
+* [in] mad pool to obtain madw from
+*
+* port_guid
+* [in] the port guid to attach to.
+*
+* RETURN VALUE
+* Bind handle to be used for later SA queries or OSM_BIND_INVALID_HANDLE
+*
+* NOTES
+*
+* SEE ALSO
+* osmv_query_sa
+*********/
+
+
+/****f* OpenSM Vendor SA Client/osmv_query_sa
+* NAME
+* osmv_query_sa
+*
+* DESCRIPTION
+* Query the SA given an SA query request (similar to IBAL ib_query).
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osmv_query_sa(
+ IN osm_bind_handle_t h_bind,
+ IN const osmv_query_req_t * const p_query_req
+ );
+/*
+* PARAMETERS
+* h_bind
+* [in] bind handle for this port. Should be previously
+* obtained by calling osmv_bind_sa
+*
+* p_query_req
+* [in] an SA query request structure.
+*
+* RETURN VALUE
+* IB_SUCCESS if completed successfuly (or in ASYNC mode
+* if the erquest was sent).
+*
+* NOTES
+*
+* SEE ALSO
+* osmv_bind_sa
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_SA_API_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Include file that defines which vendor files to compile.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_VENDOR_SELECT_H_
+#define _OSM_VENDOR_SELECT_H_
+
+/////////////////////////////////////////////////////
+//
+// MAD INTERFACE SELECTION
+//
+/////////////////////////////////////////////////////
+
+/*
+ TEST and UMADT must be specified in the 'make' command line,
+ with VENDOR=test or VENDOR=umadt.
+*/
+#ifndef OSM_VENDOR_INTF_OPENIB
+#ifndef OSM_VENDOR_INTF_TEST
+#ifndef OSM_VENDOR_INTF_UMADT
+#ifndef OSM_VENDOR_INTF_MTL
+#ifndef OSM_VENDOR_INTF_TS
+#ifndef OSM_VENDOR_INTF_SIM
+#ifndef OSM_VENDOR_INTF_AL
+#define OSM_VENDOR_INTF_AL
+#endif /* AL */
+#endif /* TS */
+#endif /* SIM */
+#endif /* MTL */
+#endif /* UMADT */
+#endif /* TEST */
+#endif /* OPENIB */
+
+#endif /* _OSM_VENDOR_SELECT_H_ */
--- /dev/null
+#ifndef _OSM_COMMON_H_
+#define _OSM_COMMON_H_
+
+#include <winsock2.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#pragma warning(disable : 4996)
+#pragma warning(disable : 4100)
+
+struct timezone {
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+/* Global variables for getopt_long */
+char *optarg;
+/*
+extern int optind;
+extern int opterr;
+extern int optopt;
+extern int iArg;
+ */
+struct option
+{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+
+/************************************************************************/
+static char*
+get_char_option(const char* optstring,
+ char*const* argv,int argc,
+ int iArg, int* opt_ind,char* opt_p);
+int
+getopt_long_only(int argc, char *const*argv,
+ const char *optstring,
+ const struct option *longopts, int *longindex);
+/**************************************************************************/
+static __inline
+void FileTimeToTimeval(LPFILETIME pft, struct timeval * ptv)
+{ /* Note that LONGLONG is a 64-bit value */
+LONGLONG ll;
+
+if(!pft || !ptv)
+goto Exit;
+
+ll = ((LONGLONG) pft->dwHighDateTime << 32);
+ll += (LONGLONG) pft->dwLowDateTime;
+#ifdef __GNUC__
+ll -= 116444736000000000ll;
+#else
+ll -= 116444736000000000;
+#endif
+
+ptv->tv_sec = (long) (ll / 10000000);
+ptv->tv_usec = (long) (ll - ((LONGLONG)(ptv->tv_sec) * 10000000)) / 10;
+
+Exit:;
+}/* FileTimeToTimeval */
+
+/********************************************************************************/
+static __inline
+int gettimeofday(struct timeval *ptv, struct timezone *tzp)
+{
+static int QueryCounter = 2;
+FILETIME CurrentTime;
+/* TODO : We need to add it , since in DDK - compiler does not like vars that are not in use */
+UNREFERENCED_PARAMETER(tzp);
+if(!ptv)
+goto Exit;
+
+if(QueryCounter)
+{
+static LARGE_INTEGER Frequency;
+static LARGE_INTEGER Offset; /* counter offset for right time*/
+static LARGE_INTEGER LastCounter;
+LARGE_INTEGER Time;
+LARGE_INTEGER Counter;
+/* HANDLE hThread = GetCurrentThread();
+int ThreadPrio = GetThreadPriority(hThread);
+
+SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); */
+GetSystemTimeAsFileTime(&CurrentTime);
+QueryPerformanceCounter(&Counter);
+/* SetThreadPriority(hThread, ThreadPrio); */
+
+if(QueryCounter == 2)
+{
+QueryCounter = 1;
+if(!QueryPerformanceFrequency(&Frequency))
+{
+QueryCounter = 0;
+Frequency.QuadPart = 10000000; /* prevent division by 0 */
+}
+
+/* get time as a large integer */
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */
+Offset.LowPart = CurrentTime.dwLowDateTime;
+Offset.HighPart = (LONG) CurrentTime.dwHighDateTime;
+Offset.QuadPart -= Counter.QuadPart * 10000000 / Frequency.QuadPart;
+}
+
+/* Convert counter to a 100 nanoseconds resolution timer value. */
+
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */
+Counter.QuadPart *= 10000000; /* Because we need time stamp in units of 100 ns */
+Counter.QuadPart /= Frequency.QuadPart; /* counter of 0.1 microseconds */
+
+if(LastCounter.QuadPart > Counter.QuadPart)
+{ /* Counter value wrapped */
+#ifdef __GNUC__
+Offset.QuadPart += (0x7f00000000ll * 10000000ll) / Frequency.QuadPart;
+#else
+Offset.QuadPart += (0x7f00000000 * 10000000) / Frequency.QuadPart;
+#endif
+}
+LastCounter = Counter;
+
+/* Add the in previous call calculated offset */
+Counter.QuadPart += Offset.QuadPart;
+
+/* get time as a large integer */
+Time.LowPart = CurrentTime.dwLowDateTime;
+Time.HighPart = (LONG) CurrentTime.dwHighDateTime;
+
+/* keep time difference within an interval of +- 0.1 seconds
+relative to the time function by adjusting the counters offset */
+
+if(((Time.QuadPart + 1000000) < Counter.QuadPart) ||
+((Time.QuadPart - 1000000) > Counter.QuadPart))
+{ /* Adjust the offset */
+Offset.QuadPart += Time.QuadPart - Counter.QuadPart;
+Counter.QuadPart = Time.QuadPart;
+}
+
+/* Now let's use the adjusted performance counter time for the time stamp */
+CurrentTime.dwLowDateTime = Counter.LowPart;
+CurrentTime.dwHighDateTime = Counter.HighPart;
+}
+else
+{
+GetSystemTimeAsFileTime(&CurrentTime);
+}
+
+FileTimeToTimeval(&CurrentTime,ptv);
+
+Exit:;
+return(0);
+}/* int gettimeofday(struct timeval *ptv, void *tzp) */
+/*****************************************************************************/
+
+
+
+
+#define getpid() GetCurrentProcessId()
+#define sleep(sec) SleepEx((sec)*1000,TRUE)
+#define usleep(usec) SleepEx(usec/1000,TRUE)
+//#define MT_ALIGN8 __declspec(align(8))
+/* Verify the correct ETIMEDOUT value is defined in all compiled files */
+#ifndef ETIMEDOUT
+#define ETIMEDOUT (10060)
+#endif
+#define strtoull _strtoui64
+#define OSM_MAX_LOG_NAME_SIZE 2048
+#define unlink(str) _unlink(str)
+#define strnicmp _strnicmp
+
+/* The following defines replace syslog.h */
+#define openlog(a,b,c)
+
+#define closelog()
+
+static __inline void
+syslog(int priority, ...) {}
+
+#define LOG_ERR 0
+#define LOG_WARNING 1
+#define LOG_INFO 2
+/*****************************************/
+
+/****f* OpenSM: osm_common/GetOsmPath
+* NAME
+* GetOsmPath
+*
+* DESCRIPTION
+* The function retrieve the temp path defined in Windows using its API
+*
+* SYNOPSIS
+*/
+char*
+GetOsmPath(void);
+/*
+* PARAMETERS
+* NONE
+*
+* RETURN VALUE
+* This function returns string containing the default temp path in windows
+*
+* NOTES
+*/
+
+/* Implementation of strtok_r for windows: since strtok in windows is safe,
+ just ignore the last variable, and call strtok. */
+static inline
+char *strtok_r(char *s1, const char *s2, char **lasts)
+{
+ return strtok(s1, s2);
+}
+#endif /* _OSM_COMMON_H_ */
--- /dev/null
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
--- /dev/null
+!if $(FREEBUILD)
+TARGETNAME=opensm_ibal
+!else
+TARGETNAME=opensm_ibald
+!endif
+TARGETTYPE=LIBRARY
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+USE_NTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+ osm_log.c \
+ osm_mad_pool.c \
+ osm_helper.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+ $(LIBPATH)\*\ibal.lib \
+ $(LIBPATH)\*\complib.lib \
+ $(TARGETPATH)\*\osmv_ibal.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+ $(LIBPATH)\*\ibald.lib \
+ $(LIBPATH)\*\complibd.lib \
+ $(TARGETPATH)\*\osmv_ibald.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+ $(OSM_HOME)\include; \
+ $(OSM_HOME); \
+ $(WINIBHOME)\inc; \
+ $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of opensm helper functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.19 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_log.h>
+
+#define LINE_LENGTH 256
+
+/* we use two tables - one for queries and one for responses */
+const char* const __ib_sa_method_str[] =
+{
+ "RESERVED", /* 0 */
+ "SubnAdmGet", /* 1 */
+ "SubnAdmSet", /* 2 */
+ "RESERVED", /* 3 */
+ "RESERVED", /* 4 */
+ "RESERVED", /* 5 */
+ "SubnAdmReport", /* 6 */
+ "RESERVED", /* 7 */
+ "RESERVED", /* 8 */
+ "RESERVED", /* 9 */
+ "RESERVED", /* A */
+ "RESERVED", /* B */
+ "RESERVED", /* C */
+ "RESERVED", /* D */
+ "RESERVED", /* E */
+ "RESERVED", /* F */
+ "RESERVED", /* 10 */
+ "RESERVED", /* 11 */
+ "SubnAdmGetTable", /* 12 */
+ "SubnAdmGetTraceTable", /* 13 */
+ "SubnAdmGetMulti", /* 14 */
+ "SubnAdmDelete", /* 15 */
+ "UNKNOWN" /* 16 */
+};
+
+const char* const __ib_sa_resp_method_str[] =
+{
+ "RESERVED", /* 80 */
+ "SubnAdmGetResp", /* 81 */
+ "RESERVED (SetResp?)", /* 82 */
+ "RESERVED", /* 83 */
+ "RESERVED", /* 84 */
+ "RESERVED", /* 85 */
+ "SubnAdmReportResp", /* 86 */
+ "RESERVED", /* 87 */
+ "RESERVED", /* 88 */
+ "RESERVED", /* 89 */
+ "RESERVED", /* 8A */
+ "RESERVED", /* 8B */
+ "RESERVED", /* 8C */
+ "RESERVED", /* 8D */
+ "RESERVED", /* 8E */
+ "RESERVED", /* 8F */
+ "RESERVED", /* 90 */
+ "RESERVED", /* 91 */
+ "SubnAdmGetTableResp", /* 92 */
+ "RESERVED", /* 93 */
+ "SubnAdmGetMultiResp", /* 94 */
+ "SubnAdmDeleteResp", /* 95 */
+ "UNKNOWN"
+};
+
+#define OSM_SA_METHOD_STR_UNKNOWN_VAL 0x16
+
+const char* const __ib_sm_method_str[] =
+{
+ "RESERVED0", /* 0 */
+ "SubnGet", /* 1 */
+ "SubnSet", /* 2 */
+ "RESERVED3", /* 3 */
+ "RESERVED4", /* 4 */
+ "SubnTrap", /* 5 */
+ "RESERVED6", /* 6 */
+ "SubnTrapRepress", /* 7 */
+ "RESERVED8", /* 8 */
+ "RESERVED9", /* 9 */
+ "RESERVEDA", /* A */
+ "RESERVEDB", /* B */
+ "RESERVEDC", /* C */
+ "RESERVEDD", /* D */
+ "RESERVEDE", /* E */
+ "RESERVEDF", /* F */
+ "RESERVED10", /* 10 */
+ "SubnGetResp", /* 11 */
+ "RESERVED12", /* 12 */
+ "RESERVED13", /* 13 */
+ "RESERVED14", /* 14 */
+ "RESERVED15", /* 15 */
+ "RESERVED16", /* 16 */
+ "RESERVED17", /* 17 */
+ "RESERVED18", /* 18 */
+ "RESERVED19", /* 19 */
+ "RESERVED1A", /* 1A */
+ "RESERVED1B", /* 1B */
+ "RESERVED1C", /* 1C */
+ "RESERVED1D", /* 1D */
+ "RESERVED1E", /* 1E */
+ "RESERVED1F", /* 1F */
+ "UNKNOWN" /* 20 */
+};
+
+#define OSM_SM_METHOD_STR_UNKNOWN_VAL 0x21
+
+const char* const __ib_sm_attr_str[] =
+{
+ "RESERVED", /* 0 */
+ "ClassPortInfo", /* 1 */
+ "Notice", /* 2 */
+ "InformInfo", /* 3 */
+ "RESERVED", /* 4 */
+ "RESERVED", /* 5 */
+ "RESERVED", /* 6 */
+ "RESERVED", /* 7 */
+ "RESERVED", /* 8 */
+ "RESERVED", /* 9 */
+ "RESERVED", /* A */
+ "RESERVED", /* B */
+ "RESERVED", /* C */
+ "RESERVED", /* D */
+ "RESERVED", /* E */
+ "RESERVED", /* F */
+ "NodeDescription", /* 10 */
+ "NodeInfo", /* 11 */
+ "SwitchInfo", /* 12 */
+ "UNKNOWN", /* 13 */
+ "GUIDInfo", /* 14 */
+ "PortInfo", /* 15 */
+ "P_KeyTable", /* 16 */
+ "SLtoVLMappingTable", /* 17 */
+ "VLArbitrationTable", /* 18 */
+ "LinearForwardingTable", /* 19 */
+ "RandomForwardingTable", /* 1A */
+ "MulticastForwardingTable", /* 1B */
+ "UNKNOWN", /* 1C */
+ "UNKNOWN", /* 1D */
+ "UNKNOWN", /* 1E */
+ "UNKNOWN", /* 1F */
+ "SMInfo", /* 20 */
+ "UNKNOWN" /* 21 - always highest value*/
+};
+
+#define OSM_SM_ATTR_STR_UNKNOWN_VAL 0x21
+
+const char* const __ib_sa_attr_str[] =
+{
+ "RESERVED", /* 0 */
+ "ClassPortInfo", /* 1 */
+ "Notice", /* 2 */
+ "InformInfo", /* 3 */
+ "RESERVED", /* 4 */
+ "RESERVED", /* 5 */
+ "RESERVED", /* 6 */
+ "RESERVED", /* 7 */
+ "RESERVED", /* 8 */
+ "RESERVED", /* 9 */
+ "RESERVED", /* A */
+ "RESERVED", /* B */
+ "RESERVED", /* C */
+ "RESERVED", /* D */
+ "RESERVED", /* E */
+ "RESERVED", /* F */
+ "RESERVED", /* 10 */
+ "NodeRecord", /* 11 */
+ "PortInfoRecord", /* 12 */
+ "SLtoVLMappingTableRecord", /* 13 */
+ "SwitchInfoRecord", /* 14 */
+ "LinearForwardingTableRecord", /* 15 */
+ "RandomForwardingTableRecord", /* 16 */
+ "MulticastForwardingTableRecord", /* 17 */
+ "SMInfoRecord", /* 18 */
+ "RESERVED", /* 19 */
+ "RandomForwardingTable", /* 1A */
+ "MulticastForwardingTable", /* 1B */
+ "UNKNOWN", /* 1C */
+ "UNKNOWN", /* 1D */
+ "UNKNOWN", /* 1E */
+ "UNKNOWN", /* 1F */
+ "LinkRecord", /* 20 */
+ "UNKNOWN", /* 21 */
+ "UNKNOWN", /* 22 */
+ "UNKNOWN", /* 23 */
+ "UNKNOWN", /* 24 */
+ "UNKNOWN", /* 25 */
+ "UNKNOWN", /* 26 */
+ "UNKNOWN", /* 27 */
+ "UNKNOWN", /* 28 */
+ "UNKNOWN", /* 29 */
+ "UNKNOWN", /* 2A */
+ "UNKNOWN", /* 2B */
+ "UNKNOWN", /* 2C */
+ "UNKNOWN", /* 2D */
+ "UNKNOWN", /* 2E */
+ "UNKNOWN", /* 2F */
+ "GuidInfoRecord", /* 30 */
+ "ServiceRecord", /* 31 */
+ "UNKNOWN", /* 32 */
+ "P_KeyTableRecord", /* 33 */
+ "UNKNOWN", /* 34 */
+ "PathRecord", /* 35 */
+ "VLArbitrationTableRecord", /* 36 */
+ "UNKNOWN", /* 37 */
+ "MCMemberRecord", /* 38 */
+ "TraceRecord", /* 39 */
+ "MultiPathRecord", /* 3A */
+ "ServiceAssociationRecord", /* 3B */
+ "UNKNOWN" /* 3C - always highest value*/
+};
+
+#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0x3C
+
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sa_method_str(
+ IN uint8_t method )
+{
+ if (method & 0x80)
+ {
+ method = method & 0x7f;
+ if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL )
+ method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+ /* it is a response - use the reponse table */
+ return( __ib_sa_resp_method_str[method] );
+ }
+ else
+ {
+ if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL )
+ method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+ return( __ib_sa_method_str[method] );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sm_method_str(
+ IN uint8_t method )
+{
+ if (method & 0x80) method = (method & 0x0F) | 0x10;
+ if( method >= OSM_SM_METHOD_STR_UNKNOWN_VAL )
+ method = OSM_SM_METHOD_STR_UNKNOWN_VAL;
+ return( __ib_sm_method_str[method] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sm_attr_str(
+ IN ib_net16_t attr )
+{
+ uint16_t host_attr;
+ host_attr = cl_ntoh16( attr );
+
+ if( host_attr >= OSM_SM_ATTR_STR_UNKNOWN_VAL )
+ host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL;
+
+ return( __ib_sm_attr_str[host_attr] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sa_attr_str(
+ IN ib_net16_t attr )
+{
+ uint16_t host_attr;
+ host_attr = cl_ntoh16( attr );
+
+ if( host_attr >= OSM_SA_ATTR_STR_UNKNOWN_VAL )
+ host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL;
+
+ return( __ib_sa_attr_str[host_attr] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_dbg_do_line(
+ IN char** pp_local,
+ IN const uint32_t buf_size,
+ IN const char* const p_prefix_str,
+ IN const char* const p_new_str,
+ IN uint32_t* const p_total_len )
+{
+ char line[LINE_LENGTH];
+ uint32_t len;
+
+ sprintf( line, "%s%s", p_prefix_str, p_new_str );
+ len = (uint32_t) strlen( line );
+ *p_total_len += len;
+ if( *p_total_len + sizeof('\0') > buf_size )
+ return( IB_INSUFFICIENT_MEMORY );
+
+ strcpy( *pp_local, line );
+ *pp_local += len;
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dbg_get_capabilities_str(
+ IN char* p_buf,
+ IN const uint32_t buf_size,
+ IN const char* const p_prefix_str,
+ IN const ib_port_info_t* const p_pi )
+{
+ uint32_t total_len = 0;
+ char *p_local = p_buf;
+
+ strcpy( p_local, "Capabilities Mask:\n" );
+ p_local += strlen( p_local );
+
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV0 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV0\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_IS_SM\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_NOTICE\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_TRAP\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_IPD )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_IPD\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_AUTO_MIG\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_SL_MAP\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_NV_MKEY\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_NV_PKEY\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_LED_INFO\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_SM_DISAB )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_SM_DISAB\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_SYS_IMG_GUID\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV13 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV13\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV14 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV14\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV15 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV15\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_COM_MGT\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_SNMP\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_REINIT )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_REINIT\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_DEV_MGT\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_VEND_CLS\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_DR_NTC\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_CAP_NTC\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_BM )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_BM\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_LINK_RT_LATENCY\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_HAS_CLIENT_REREG\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV26 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV26\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV27 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV27\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV28)
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV28\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV29 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV29\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV30 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV30\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV31 )
+ {
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+ "IB_PORT_CAP_RESV31\n", &total_len ) != IB_SUCCESS )
+ return;
+ }
+
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_port_info(
+ IN osm_log_t* const p_log,
+ IN const ib_net64_t node_guid,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const ib_port_info_t* const p_pi,
+ IN const osm_log_level_t log_level )
+{
+ char buf[BUF_SIZE];
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "PortInfo dump:\n"
+ "\t\t\t\tport number.............0x%X\n"
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+ "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+ "\t\t\t\tbase_lid................0x%X\n"
+ "\t\t\t\tmaster_sm_base_lid......0x%X\n"
+ "\t\t\t\tcapability_mask.........0x%X\n"
+ "\t\t\t\tdiag_code...............0x%X\n"
+ "\t\t\t\tm_key_lease_period......0x%X\n"
+ "\t\t\t\tlocal_port_num..........0x%X\n"
+ "\t\t\t\tlink_width_enabled......0x%X\n"
+ "\t\t\t\tlink_width_supported....0x%X\n"
+ "\t\t\t\tlink_width_active.......0x%X\n"
+ "\t\t\t\tlink_speed_supported....0x%X\n"
+ "\t\t\t\tport_state..............%s\n"
+ "\t\t\t\tstate_info2.............0x%X\n"
+ "\t\t\t\tm_key_protect_bits......0x%X\n"
+ "\t\t\t\tlmc.....................0x%X\n"
+ "\t\t\t\tlink_speed..............0x%X\n"
+ "\t\t\t\tmtu_smsl................0x%X\n"
+ "\t\t\t\tvl_cap_init_type........0x%X\n"
+ "\t\t\t\tvl_high_limit...........0x%X\n"
+ "\t\t\t\tvl_arb_high_cap.........0x%X\n"
+ "\t\t\t\tvl_arb_low_cap..........0x%X\n"
+ "\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+ "\t\t\t\tvl_stall_life...........0x%X\n"
+ "\t\t\t\tvl_enforce..............0x%X\n"
+ "\t\t\t\tm_key_violations........0x%X\n"
+ "\t\t\t\tp_key_violations........0x%X\n"
+ "\t\t\t\tq_key_violations........0x%X\n"
+ "\t\t\t\tguid_cap................0x%X\n"
+ "\t\t\t\tsubnet_timeout..........0x%X\n"
+ "\t\t\t\tresp_time_value.........0x%X\n"
+ "\t\t\t\terror_threshold.........0x%X\n"
+ "",
+ port_num,
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( p_pi->m_key ),
+ cl_ntoh64( p_pi->subnet_prefix ),
+ cl_ntoh16( p_pi->base_lid ),
+ cl_ntoh16( p_pi->master_sm_base_lid ),
+ cl_ntoh32( p_pi->capability_mask ),
+ cl_ntoh16( p_pi->diag_code ),
+ cl_ntoh16( p_pi->m_key_lease_period ),
+ p_pi->local_port_num,
+ p_pi->link_width_enabled,
+ p_pi->link_width_supported,
+ p_pi->link_width_active,
+ ib_port_info_get_link_speed_sup( p_pi ),
+ ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),
+ p_pi->state_info2,
+ ib_port_info_get_mpb( p_pi ),
+ ib_port_info_get_lmc( p_pi ),
+ p_pi->link_speed,
+ p_pi->mtu_smsl,
+ p_pi->vl_cap,
+ p_pi->vl_high_limit,
+ p_pi->vl_arb_high_cap,
+ p_pi->vl_arb_low_cap,
+ p_pi->mtu_cap,
+ p_pi->vl_stall_life,
+ p_pi->vl_enforce,
+ cl_ntoh16( p_pi->m_key_violations ),
+ cl_ntoh16( p_pi->p_key_violations ),
+ cl_ntoh16( p_pi->q_key_violations ),
+ p_pi->guid_cap,
+ ib_port_info_get_timeout(p_pi),
+ p_pi->resp_time_value,
+ p_pi->error_threshold
+ );
+
+ /* show the capabilities mask */
+ osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );
+
+ osm_log( p_log, log_level,
+ "%s", buf );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_dump_portinfo_record(
+ IN osm_log_t* const p_log,
+ IN const ib_portinfo_record_t* const p_pir,
+ IN const osm_log_level_t log_level )
+{
+ char buf[BUF_SIZE];
+ const ib_port_info_t * const p_pi = &p_pir->port_info;
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "PortInfo Record dump:\n"
+ "\t\t\t\tRID\n"
+ "\t\t\t\tEndPortLid..............0x%X\n"
+ "\t\t\t\tPortNum.................0x%X\n"
+ "\t\t\t\tReserved................0x%X\n"
+ "\t\t\t\tPortInfo dump\n"
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+ "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+ "\t\t\t\tbase_lid................0x%X\n"
+ "\t\t\t\tmaster_sm_base_lid......0x%X\n"
+ "\t\t\t\tcapability_mask.........0x%X\n"
+ "\t\t\t\tdiag_code...............0x%X\n"
+ "\t\t\t\tm_key_lease_period......0x%X\n"
+ "\t\t\t\tlocal_port_num..........0x%X\n"
+ "\t\t\t\tlink_width_enabled......0x%X\n"
+ "\t\t\t\tlink_width_supported....0x%X\n"
+ "\t\t\t\tlink_width_active.......0x%X\n"
+ "\t\t\t\tlink_speed_supported....0x%X\n"
+ "\t\t\t\tport_state..............%s\n"
+ "\t\t\t\tstate_info2.............0x%X\n"
+ "\t\t\t\tm_key_protect_bits......0x%X\n"
+ "\t\t\t\tlmc.....................0x%X\n"
+ "\t\t\t\tlink_speed..............0x%X\n"
+ "\t\t\t\tmtu_smsl................0x%X\n"
+ "\t\t\t\tvl_cap_init_type........0x%X\n"
+ "\t\t\t\tvl_high_limit...........0x%X\n"
+ "\t\t\t\tvl_arb_high_cap.........0x%X\n"
+ "\t\t\t\tvl_arb_low_cap..........0x%X\n"
+ "\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+ "\t\t\t\tvl_stall_life...........0x%X\n"
+ "\t\t\t\tvl_enforce..............0x%X\n"
+ "\t\t\t\tm_key_violations........0x%X\n"
+ "\t\t\t\tp_key_violations........0x%X\n"
+ "\t\t\t\tq_key_violations........0x%X\n"
+ "\t\t\t\tguid_cap................0x%X\n"
+ "\t\t\t\tsubnet_timeout..........0x%X\n"
+ "\t\t\t\tresp_time_value.........0x%X\n"
+ "\t\t\t\terror_threshold.........0x%X\n"
+ "",
+ cl_ntoh16(p_pir->lid),
+ p_pir->port_num,
+ p_pir->resv,
+ cl_ntoh64( p_pi->m_key ),
+ cl_ntoh64( p_pi->subnet_prefix ),
+ cl_ntoh16( p_pi->base_lid ),
+ cl_ntoh16( p_pi->master_sm_base_lid ),
+ cl_ntoh32( p_pi->capability_mask ),
+ cl_ntoh16( p_pi->diag_code ),
+ cl_ntoh16( p_pi->m_key_lease_period ),
+ p_pi->local_port_num,
+ p_pi->link_width_enabled,
+ p_pi->link_width_supported,
+ p_pi->link_width_active,
+ ib_port_info_get_link_speed_sup( p_pi ),
+ ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),
+ p_pi->state_info2,
+ ib_port_info_get_mpb( p_pi ),
+ ib_port_info_get_lmc( p_pi ),
+ p_pi->link_speed,
+ p_pi->mtu_smsl,
+ p_pi->vl_cap,
+ p_pi->vl_high_limit,
+ p_pi->vl_arb_high_cap,
+ p_pi->vl_arb_low_cap,
+ p_pi->mtu_cap,
+ p_pi->vl_stall_life,
+ p_pi->vl_enforce,
+ cl_ntoh16( p_pi->m_key_violations ),
+ cl_ntoh16( p_pi->p_key_violations ),
+ cl_ntoh16( p_pi->q_key_violations ),
+ p_pi->guid_cap,
+ ib_port_info_get_timeout( p_pi ),
+ p_pi->resp_time_value,
+ p_pi->error_threshold
+ );
+
+ /* show the capabilities mask */
+ osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );
+
+ osm_log( p_log, log_level,
+ "%s", buf );
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_node_info(
+ IN osm_log_t* const p_log,
+ IN const ib_node_info_t* const p_ni,
+ IN const osm_log_level_t log_level )
+{
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "NodeInfo dump:\n"
+ "\t\t\t\tbase_version............0x%X\n"
+ "\t\t\t\tclass_version...........0x%X\n"
+ "\t\t\t\tnode_type...............%s\n"
+ "\t\t\t\tnum_ports...............0x%X\n"
+ "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tpartition_cap...........0x%X\n"
+ "\t\t\t\tdevice_id...............0x%X\n"
+ "\t\t\t\trevision................0x%X\n"
+ "\t\t\t\tport_num................0x%X\n"
+ "\t\t\t\tvendor_id...............0x%X\n"
+ "",
+ p_ni->base_version,
+ p_ni->class_version,
+ ib_get_node_type_str( p_ni->node_type ),
+ p_ni->num_ports,
+ cl_ntoh64( p_ni->sys_guid ),
+ cl_ntoh64( p_ni->node_guid ),
+ cl_ntoh64( p_ni->port_guid ),
+ cl_ntoh16( p_ni->partition_cap ),
+ cl_ntoh16( p_ni->device_id ),
+ cl_ntoh32( p_ni->revision ),
+ ib_node_info_get_local_port_num( p_ni ),
+ cl_ntoh32( ib_node_info_get_vendor_id( p_ni ) )
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_node_record(
+ IN osm_log_t* const p_log,
+ IN const ib_node_record_t* const p_nr,
+ IN const osm_log_level_t log_level )
+{
+ const ib_node_info_t * const p_ni = &p_nr->node_info;
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "NodeRecord dump:\n"
+ "\t\t\t\tRID\n"
+ "\t\t\t\tLid.....................0x%X\n"
+ "\t\t\t\tReserved................0x%X\n"
+ "\t\t\t\tNodeInfoDump\n"
+ "\t\t\t\tbase_version............0x%X\n"
+ "\t\t\t\tclass_version...........0x%X\n"
+ "\t\t\t\tnode_type...............%s\n"
+ "\t\t\t\tnum_ports...............0x%X\n"
+ "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+ "\t\t\t\tpartition_cap...........0x%X\n"
+ "\t\t\t\tdevice_id...............0x%X\n"
+ "\t\t\t\trevision................0x%X\n"
+ "\t\t\t\tport_num................0x%X\n"
+ "\t\t\t\tvendor_id...............0x%X\n"
+ "\t\t\t\tNodeDescription\n"
+ "\t\t\t\t%s\n"
+ "",
+ cl_ntoh16(p_nr->lid),
+ cl_ntoh16(p_nr->resv),
+ p_ni->base_version,
+ p_ni->class_version,
+ ib_get_node_type_str( p_ni->node_type ),
+ p_ni->num_ports,
+ cl_ntoh64( p_ni->sys_guid ),
+ cl_ntoh64( p_ni->node_guid ),
+ cl_ntoh64( p_ni->port_guid ),
+ cl_ntoh16( p_ni->partition_cap ),
+ cl_ntoh16( p_ni->device_id ),
+ cl_ntoh32( p_ni->revision ),
+ ib_node_info_get_local_port_num( p_ni ),
+ cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),
+ p_nr->node_desc.description
+ );
+
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_path_record(
+ IN osm_log_t* const p_log,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_log_level_t log_level )
+{
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "PathRecord dump:\n"
+ "\t\t\t\tresv0...................0x%016" PRIx64 "\n"
+ "\t\t\t\tdgid....................0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n"
+ "\t\t\t\tsgid....................0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n"
+ "\t\t\t\tdlid....................0x%X\n"
+ "\t\t\t\tslid....................0x%X\n"
+ "\t\t\t\thop_flow_raw............0x%X\n"
+ "\t\t\t\ttclass..................0x%X\n"
+ "\t\t\t\tnum_path_revers.........0x%X\n"
+ "\t\t\t\tpkey....................0x%X\n"
+ "\t\t\t\tsl......................0x%X\n"
+ "\t\t\t\tmtu.....................0x%X\n"
+ "\t\t\t\trate....................0x%X\n"
+ "\t\t\t\tpkt_life................0x%X\n"
+ "\t\t\t\tpreference..............0x%X\n"
+ "\t\t\t\tresv2...................0x%X\n"
+ "\t\t\t\tresv3...................0x%X\n"
+ "",
+ *(uint64_t*)p_pr->resv0,
+ cl_ntoh64( p_pr->dgid.unicast.prefix ),
+ cl_ntoh64( p_pr->dgid.unicast.interface_id ),
+ cl_ntoh64( p_pr->sgid.unicast.prefix ),
+ cl_ntoh64( p_pr->sgid.unicast.interface_id ),
+ cl_ntoh16( p_pr->dlid ),
+ cl_ntoh16( p_pr->slid ),
+ cl_ntoh32( p_pr->hop_flow_raw ),
+ p_pr->tclass,
+ p_pr->num_path,
+ cl_ntoh16( p_pr->pkey ),
+ cl_ntoh16( p_pr->sl ),
+ cl_ntoh16( p_pr->sl ),
+ p_pr->mtu,
+ p_pr->rate,
+ p_pr->pkt_life,
+ p_pr->preference,
+ *(uint32_t*)&p_pr->resv2,
+ *((uint16_t*)&p_pr->resv2 + 2)
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_mc_record(
+ IN osm_log_t* const p_log,
+ IN const ib_member_rec_t* const p_mcmr,
+ IN const osm_log_level_t log_level )
+{
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "MCMember Record dump:\n"
+ "\t\t\t\tMGID....................0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n"
+ "\t\t\t\tPortGid.................0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n"
+ "\t\t\t\tqkey....................0x%X\n"
+ "\t\t\t\tMlid....................0x%X\n"
+ "\t\t\t\tScopeState..............0x%X\n"
+ "\t\t\t\tRate....................0x%X\n"
+ "\t\t\t\tMtu.....................0x%X\n"
+ "\t\t\t\tTClass..................0x%X\n"
+ "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n"
+ "",
+ cl_ntoh64( p_mcmr->mgid.unicast.prefix ),
+ cl_ntoh64( p_mcmr->mgid.unicast.interface_id ),
+ cl_ntoh64( p_mcmr->port_gid.unicast.prefix ),
+ cl_ntoh64( p_mcmr->port_gid.unicast.interface_id ),
+ cl_ntoh32( p_mcmr->qkey ),
+ cl_ntoh16( p_mcmr->mlid ),
+ p_mcmr->scope_state,
+ p_mcmr->rate,
+ p_mcmr->mtu,
+ p_mcmr->tclass,
+ cl_ntoh32( p_mcmr->sl_flow_hop )
+ );
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_service_record(
+ IN osm_log_t* const p_log,
+ IN const ib_service_record_t* const p_sr,
+ IN const osm_log_level_t log_level )
+{
+ char buf_service_key[33];
+ char buf_service_name[65];
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ sprintf(buf_service_key,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ p_sr->service_key[0],
+ p_sr->service_key[1],
+ p_sr->service_key[2],
+ p_sr->service_key[3],
+ p_sr->service_key[4],
+ p_sr->service_key[5],
+ p_sr->service_key[6],
+ p_sr->service_key[7],
+ p_sr->service_key[8],
+ p_sr->service_key[9],
+ p_sr->service_key[10],
+ p_sr->service_key[11],
+ p_sr->service_key[12],
+ p_sr->service_key[13],
+ p_sr->service_key[14],
+ p_sr->service_key[15]);
+ strncpy(buf_service_name, (char *)p_sr->service_name, 64);
+ buf_service_name[64] = '\0';
+
+ osm_log( p_log, log_level,
+ "ServiceRecord dump:\n"
+ "\t\t\t\tServiceID...............0x%016" PRIx64 "\n"
+ "\t\t\t\tServiceGID..............0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n"
+ "\t\t\t\tServiceP_Key............0x%X\n"
+ "\t\t\t\tServiceLease............0x%X\n"
+ "\t\t\t\tServiceKey..............%s\n"
+ "\t\t\t\tServiceName.............%s\n"
+ "\t\t\t\tServiceData8.1..........0x%X\n"
+ "\t\t\t\tServiceData8.2..........0x%X\n"
+ "\t\t\t\tServiceData8.3..........0x%X\n"
+ "\t\t\t\tServiceData8.4..........0x%X\n"
+ "\t\t\t\tServiceData8.5..........0x%X\n"
+ "\t\t\t\tServiceData8.6..........0x%X\n"
+ "\t\t\t\tServiceData8.7..........0x%X\n"
+ "\t\t\t\tServiceData8.8..........0x%X\n"
+ "\t\t\t\tServiceData8.9..........0x%X\n"
+ "\t\t\t\tServiceData8.10.........0x%X\n"
+ "\t\t\t\tServiceData8.11.........0x%X\n"
+ "\t\t\t\tServiceData8.12.........0x%X\n"
+ "\t\t\t\tServiceData8.13.........0x%X\n"
+ "\t\t\t\tServiceData8.14.........0x%X\n"
+ "\t\t\t\tServiceData8.15.........0x%X\n"
+ "\t\t\t\tServiceData8.16.........0x%X\n"
+ "\t\t\t\tServiceData16.1.........0x%X\n"
+ "\t\t\t\tServiceData16.2.........0x%X\n"
+ "\t\t\t\tServiceData16.3.........0x%X\n"
+ "\t\t\t\tServiceData16.4.........0x%X\n"
+ "\t\t\t\tServiceData16.5.........0x%X\n"
+ "\t\t\t\tServiceData16.6.........0x%X\n"
+ "\t\t\t\tServiceData16.7.........0x%X\n"
+ "\t\t\t\tServiceData16.8.........0x%X\n"
+ "\t\t\t\tServiceData32.1.........0x%X\n"
+ "\t\t\t\tServiceData32.2.........0x%X\n"
+ "\t\t\t\tServiceData32.3.........0x%X\n"
+ "\t\t\t\tServiceData32.4.........0x%X\n"
+ "\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n"
+ "\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\n"
+ "",
+
+ cl_ntoh64( p_sr->service_id ),
+ cl_ntoh64( p_sr->service_gid.unicast.prefix ),
+ cl_ntoh64( p_sr->service_gid.unicast.interface_id ),
+ cl_ntoh16( p_sr->service_pkey ),
+ cl_ntoh32( p_sr->service_lease ),
+ buf_service_key,
+ buf_service_name,
+ p_sr->service_data8[0], p_sr->service_data8[1],
+ p_sr->service_data8[2], p_sr->service_data8[3],
+ p_sr->service_data8[4], p_sr->service_data8[5],
+ p_sr->service_data8[6], p_sr->service_data8[7],
+ p_sr->service_data8[8], p_sr->service_data8[9],
+ p_sr->service_data8[10], p_sr->service_data8[11],
+ p_sr->service_data8[12], p_sr->service_data8[13],
+ p_sr->service_data8[14], p_sr->service_data8[15],
+ cl_ntoh16(p_sr->service_data16[0]),
+ cl_ntoh16(p_sr->service_data16[1]),
+ cl_ntoh16(p_sr->service_data16[2]),
+ cl_ntoh16(p_sr->service_data16[3]),
+ cl_ntoh16(p_sr->service_data16[4]),
+ cl_ntoh16(p_sr->service_data16[5]),
+ cl_ntoh16(p_sr->service_data16[6]),
+ cl_ntoh16(p_sr->service_data16[7]),
+ cl_ntoh32(p_sr->service_data32[0]),
+ cl_ntoh32(p_sr->service_data32[1]),
+ cl_ntoh32(p_sr->service_data32[2]),
+ cl_ntoh32(p_sr->service_data32[3]),
+ cl_ntoh64(p_sr->service_data64[0]),
+ cl_ntoh64(p_sr->service_data64[1])
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_inform_info(
+ IN osm_log_t* const p_log,
+ IN const ib_inform_info_t* const p_ii,
+ IN const osm_log_level_t log_level )
+{
+ uint32_t qpn;
+ uint8_t resp_time_val;
+ ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.qpn_resp_time_val,
+ &qpn,&resp_time_val);
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ if (p_ii->is_generic)
+ {
+ osm_log( p_log, log_level,
+ "InformInfo dump:\n"
+ "\t\t\t\tgid.....................0x%016" PRIx64 ",%016" PRIx64 "\n"
+ "\t\t\t\tlid_range_begin.........0x%X\n"
+ "\t\t\t\tlid_range_end...........0x%X\n"
+ "\t\t\t\tis_generic..............0x%X\n"
+ "\t\t\t\tsubscribe...............0x%X\n"
+ "\t\t\t\ttrap_type...............0x%X\n"
+ "\t\t\t\ttrap_num................0x%X\n"
+ "\t\t\t\tqpn.....................0x%06X\n"
+ "\t\t\t\tresp_time_val...........0x%X\n"
+ "\t\t\t\tnode_type...............0x%06X\n"
+ "",
+ cl_ntoh64( p_ii->gid.unicast.prefix ),
+ cl_ntoh64( p_ii->gid.unicast.interface_id ),
+ cl_ntoh16( p_ii->lid_range_begin ),
+ cl_ntoh16( p_ii->lid_range_end ),
+ p_ii->is_generic,
+ p_ii->subscribe,
+ cl_ntoh16( p_ii->trap_type ),
+ cl_ntoh16( p_ii->g_or_v.generic.trap_num ),
+ cl_ntoh32(qpn),
+ resp_time_val,
+ cl_ntoh32(ib_inform_info_get_node_type( p_ii ))
+ );
+ }
+ else
+ {
+ osm_log( p_log, log_level,
+ "InformInfo dump:\n"
+ "\t\t\t\tgid.....................0x%016" PRIx64 ",%016" PRIx64 "\n"
+ "\t\t\t\tlid_range_begin.........0x%X\n"
+ "\t\t\t\tlid_range_end...........0x%X\n"
+ "\t\t\t\tis_generic..............0x%X\n"
+ "\t\t\t\tsubscribe...............0x%X\n"
+ "\t\t\t\ttrap_type...............0x%X\n"
+ "\t\t\t\tdev_id..................0x%X\n"
+ "\t\t\t\tqpn.....................0x%06X\n"
+ "\t\t\t\tresp_time_val...........0x%X\n"
+ "\t\t\t\tvendor_id...............0x%06X\n"
+ "",
+ cl_ntoh64( p_ii->gid.unicast.prefix ),
+ cl_ntoh64( p_ii->gid.unicast.interface_id ),
+ cl_ntoh16( p_ii->lid_range_begin ),
+ cl_ntoh16( p_ii->lid_range_end ),
+ p_ii->is_generic,
+ p_ii->subscribe,
+ cl_ntoh16( p_ii->trap_type ),
+ cl_ntoh16( p_ii->g_or_v.vend.dev_id ),
+ cl_ntoh32(qpn),
+ resp_time_val,
+ cl_ntoh32(ib_inform_info_get_node_type( p_ii ))
+ );
+ }
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_link_record(
+ IN osm_log_t* const p_log,
+ IN const ib_link_record_t* const p_lr,
+ IN const osm_log_level_t log_level )
+{
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, log_level,
+ "LinkRecord dump:\n"
+ "\t\t\t\tfrom_lid................0x%X\n"
+ "\t\t\t\tfrom_port_num...........0x%X\n"
+ "\t\t\t\tto_port_num.............0x%X\n"
+ "\t\t\t\tto_lid..................0x%X\n"
+ "",
+ cl_ntoh16( p_lr->from_lid ),
+ p_lr->from_port_num,
+ p_lr->to_port_num,
+ cl_ntoh16( p_lr->to_lid )
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_switch_info(
+ IN osm_log_t* const p_log,
+ IN const ib_switch_info_t* const p_si,
+ IN const osm_log_level_t log_level )
+{
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "SwitchInfo dump:\n"
+ "\t\t\t\tlin_cap.................0x%X\n"
+ "\t\t\t\trand_cap................0x%X\n"
+ "\t\t\t\tmcast_cap...............0x%X\n"
+ "\t\t\t\tlin_top.................0x%X\n"
+ "\t\t\t\tdef_port................0x%X\n"
+ "\t\t\t\tdef_mcast_pri_port......0x%X\n"
+ "\t\t\t\tdef_mcast_not_port......0x%X\n"
+ "\t\t\t\tlife_state..............0x%X\n"
+ "\t\t\t\tlids_per_port...........0x%X\n"
+ "\t\t\t\tenforce_cap.............0x%X\n"
+ "\t\t\t\tflags...................0x%X\n"
+ "",
+ cl_ntoh16( p_si->lin_cap ),
+ cl_ntoh16( p_si->rand_cap ),
+ cl_ntoh16( p_si->mcast_cap ),
+ cl_ntoh16( p_si->lin_top ),
+ p_si->def_port,
+ p_si->def_mcast_pri_port,
+ p_si->def_mcast_not_port,
+ p_si->life_state,
+ cl_ntoh16( p_si->lids_per_port ),
+ cl_ntoh16( p_si->enforce_cap ),
+ p_si->flags
+ );
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_pkey_block(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint16_t block_num,
+ IN uint8_t port_num,
+ IN const ib_pkey_table_t* const p_pkey_tbl,
+ IN const osm_log_level_t log_level )
+{
+ int i;
+ char buf_line[1024];
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ buf_line[0] = '\0';
+ for (i = 0; i<32; i++)
+ sprintf( buf_line,"%s 0x%04x |",
+ buf_line, cl_ntoh16(p_pkey_tbl->pkey_entry[i]));
+
+ osm_log( p_log, log_level,
+ "P_Key table dump:\n"
+ "\t\t\tport_guid...........0x%016" PRIx64 "\n"
+ "\t\t\tblock_num...........0x%X\n"
+ "\t\t\tport_num............0x%X\n\tP_Key Table: %s\n",
+ cl_ntoh64( port_guid ),
+ block_num,
+ port_num,
+ buf_line
+ );
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_slvl_map_table(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint8_t in_port_num,
+ IN uint8_t out_port_num,
+ IN const ib_slvl_table_t* const p_slvl_tbl,
+ IN const osm_log_level_t log_level )
+{
+ uint8_t i;
+ char buf_line1[1024];
+ char buf_line2[1024];
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ buf_line1[0] = '\0';
+ buf_line2[0] = '\0';
+ for (i = 0; i<16; i++) sprintf( buf_line1,"%s %-2u |", buf_line1, i);
+ for (i = 0; i<16; i++) sprintf( buf_line2,"%s0x%01X |",
+ buf_line2, ib_slvl_table_get(p_slvl_tbl, i));
+ osm_log( p_log, log_level,
+ "SLtoVL dump:\n"
+ "\t\t\tport_guid............0x%016" PRIx64 "\n"
+ "\t\t\tin_port_num..........0x%X\n"
+ "\t\t\tout_port_num.........0x%X\n\tSL: | %s\n\tVL: | %s\n",
+ cl_ntoh64( port_guid ),
+ in_port_num,
+ out_port_num,
+ buf_line1, buf_line2
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_vl_arb_table(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint8_t block_num,
+ IN uint8_t port_num,
+ IN const ib_vl_arb_table_t* const p_vla_tbl,
+ IN const osm_log_level_t log_level )
+{
+ int i;
+ char buf_line1[1024];
+ char buf_line2[1024];
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ buf_line1[0] = '\0';
+ buf_line2[0] = '\0';
+ for (i = 0; i<32; i++) sprintf( buf_line1,"%s 0x%01X |",
+ buf_line1, p_vla_tbl->vl_entry[i].vl);
+ for (i = 0; i<32; i++) sprintf( buf_line2,"%s 0x%01X |",
+ buf_line2, p_vla_tbl->vl_entry[i].weight);
+ osm_log( p_log, log_level,
+ "VlArb dump:\n"
+ "\t\t\tport_guid...........0x%016" PRIx64 "\n"
+ "\t\t\tblock_num...........0x%X\n"
+ "\t\t\tport_num............0x%X\n\tVL : | %s\n\tWEIGHT:| %s\n",
+ cl_ntoh64( port_guid ),
+ block_num,
+ port_num,
+ buf_line1, buf_line2
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_sm_info(
+ IN osm_log_t* const p_log,
+ IN const ib_sm_info_t* const p_smi,
+ IN const osm_log_level_t log_level )
+{
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "SMInfo dump:\n"
+ "\t\t\t\tguid....................0x%016" PRIx64 "\n"
+ "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+ "\t\t\t\tact_count...............%u\n"
+ "\t\t\t\tpriority................%u\n"
+ "\t\t\t\tsm_state................%u\n"
+ "",
+ cl_ntoh64( p_smi->guid ),
+ cl_ntoh64( p_smi->sm_key ),
+ cl_ntoh32( p_smi->act_count ),
+ ib_sminfo_get_priority( p_smi ),
+ ib_sminfo_get_state( p_smi )
+ );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_notice(
+ IN osm_log_t* const p_log,
+ IN const ib_mad_notice_attr_t *p_ntci,
+ IN const osm_log_level_t log_level )
+{
+ char buff[1024];
+ buff[0] = '\0';
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ if (ib_notice_is_generic(p_ntci))
+ {
+ /* immediate data based on the trap */
+ switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) {
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ sprintf(buff,
+ "\t\t\t\tsrc_gid..................0x%016" PRIx64
+ ":0x%016" PRIx64 "\n",
+ cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.prefix),
+ cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.interface_id));
+ break;
+ case 128:
+ sprintf(buff,
+ "\t\t\t\tsw_lid...................0x%04X\n",
+ cl_ntoh16(p_ntci->data_details.ntc_128.sw_lid));
+ break;
+ case 129:
+ case 130:
+ case 131:
+ sprintf(buff,
+ "\t\t\t\tlid......................0x%04X\n"
+ "\t\t\t\tport_num.................%u\n",
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ p_ntci->data_details.ntc_129_131.port_num);
+ break;
+ case 144:
+ sprintf(buff,
+ "\t\t\t\tlid......................0x%04x\n"
+ "\t\t\t\tnew_cap_mask.............0x%08x\n",
+ cl_ntoh16(p_ntci->data_details.ntc_144.lid),
+ cl_ntoh32(p_ntci->data_details.ntc_144.new_cap_mask));
+ break;
+ case 145:
+ sprintf(buff,
+ "\t\t\t\tlid......................0x%04X\n"
+ "\t\t\t\tnew_sys_guid.............0x%016" PRIx64 "\n",
+ cl_ntoh16(p_ntci->data_details.ntc_145.lid),
+ cl_ntoh64(p_ntci->data_details.ntc_145.new_sys_guid));
+ break;
+ }
+
+ osm_log( p_log, log_level,
+ "Generic Notice dump:\n"
+ "\t\t\t\ttype....................0x%02X\n"
+ "\t\t\t\tprod_type...............%u\n"
+ "\t\t\t\ttrap_num................%u\n%s"
+ "",
+ ib_notice_get_type(p_ntci),
+ cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+ buff
+ );
+ }
+ else
+ {
+ osm_log( p_log, log_level,
+ "Vendor Notice dump:\n"
+ "\t\t\t\ttype....................0x%04x\n"
+ "\t\t\t\tvendor..................%u\n"
+ "\t\t\t\tdevice_id...............%u\n"
+ "",
+ cl_ntoh16(ib_notice_get_type(p_ntci)),
+ cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
+ cl_ntoh16(p_ntci->g_or_v.vend.dev_id)
+ );
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_dr_smp(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t log_level )
+{
+ uint32_t i;
+ char buf[BUF_SIZE];
+ char line[BUF_SIZE];
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ sprintf( buf,
+ "SMP dump:\n"
+ "\t\t\t\tbase_ver................0x%X\n"
+ "\t\t\t\tmgmt_class..............0x%X\n"
+ "\t\t\t\tclass_ver...............0x%X\n"
+ "\t\t\t\tmethod..................0x%X (%s)\n",
+ p_smp->base_ver,
+ p_smp->mgmt_class,
+ p_smp->class_ver,
+ p_smp->method, ib_get_sm_method_str(p_smp->method));
+
+ if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+ {
+ sprintf( line,
+ "\t\t\t\tD bit...................0x%X\n"
+ "\t\t\t\tstatus..................0x%X\n",
+ ib_smp_is_d(p_smp),
+ ib_smp_get_status(p_smp));
+ }
+ else
+ {
+ sprintf( line,
+ "\t\t\t\tstatus..................0x%X\n",
+ cl_ntoh16(p_smp->status));
+ }
+ strcat( buf, line );
+
+ sprintf( line,
+ "\t\t\t\thop_ptr.................0x%X\n"
+ "\t\t\t\thop_count...............0x%X\n"
+ "\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+ "\t\t\t\tattr_id.................0x%X (%s)\n"
+ "\t\t\t\tresv....................0x%X\n"
+ "\t\t\t\tattr_mod................0x%X\n"
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+ "\t\t\t\tdr_slid.................0x%X\n"
+ "\t\t\t\tdr_dlid.................0x%X\n",
+ p_smp->hop_ptr,
+ p_smp->hop_count,
+ cl_ntoh64(p_smp->trans_id),
+ cl_ntoh16(p_smp->attr_id),
+ ib_get_sm_attr_str( p_smp->attr_id ),
+ cl_ntoh16(p_smp->resv),
+ cl_ntoh32(p_smp->attr_mod),
+ cl_ntoh64(p_smp->m_key),
+ cl_ntoh16(p_smp->dr_slid),
+ cl_ntoh16(p_smp->dr_dlid)
+ );
+ strcat( buf, line );
+
+ if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+ {
+ strcat( buf, "\n\t\t\t\tInitial path: " );
+
+ for( i = 0; i <= p_smp->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_smp->initial_path[i] );
+ strcat( buf, line );
+ }
+
+ strcat( buf, "\n\t\t\t\tReturn path: " );
+
+ for( i = 0; i <= p_smp->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_smp->return_path[i] );
+ strcat( buf, line );
+ }
+
+ strcat( buf, "\n\t\t\t\tReserved: " );
+
+ for( i = 0; i < 7; i++ )
+ {
+ sprintf( line, "[%0X]", p_smp->resv1[i] );
+ strcat( buf, line );
+ }
+
+ strcat( buf, "\n" );
+
+ for( i = 0; i < 64; i += 16 )
+ {
+ sprintf( line, "\n\t\t\t\t%02X %02X %02X %02X "
+ "%02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ p_smp->data[i],
+ p_smp->data[i+1],
+ p_smp->data[i+2],
+ p_smp->data[i+3],
+ p_smp->data[i+4],
+ p_smp->data[i+5],
+ p_smp->data[i+6],
+ p_smp->data[i+7],
+ p_smp->data[i+8],
+ p_smp->data[i+9],
+ p_smp->data[i+10],
+ p_smp->data[i+11],
+ p_smp->data[i+12],
+ p_smp->data[i+13],
+ p_smp->data[i+14],
+ p_smp->data[i+15] );
+
+ strcat( buf, line );
+ }
+ }
+ else
+ {
+ /* not a Direct Route so provide source and destination lids */
+ strcat(buf, "\t\t\t\tMAD IS LID ROUTED\n");
+ }
+
+ osm_log( p_log, log_level,
+ "%s\n", buf );
+
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_sa_mad(
+ IN osm_log_t* const p_log,
+ IN const ib_sa_mad_t* const p_mad,
+ IN const osm_log_level_t log_level )
+{
+ char buf[BUF_SIZE];
+
+ /* make sure the mad is valid */
+ if (p_mad == NULL)
+ {
+ osm_log( p_log, log_level,
+ "NULL MAD POINTER\n");
+ return;
+ }
+
+ if( osm_log_is_active( p_log, log_level ) )
+ {
+ sprintf( buf,
+ "SA MAD dump:\n"
+ "\t\t\t\tbase_ver................0x%X\n"
+ "\t\t\t\tmgmt_class..............0x%X\n"
+ "\t\t\t\tclass_ver...............0x%X\n"
+ "\t\t\t\tmethod..................0x%X (%s)\n"
+ "\t\t\t\tstatus..................0x%X\n"
+ "\t\t\t\tresv....................0x%X\n"
+ "\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+ "\t\t\t\tattr_id.................0x%X (%s)\n"
+ "\t\t\t\tresv1...................0x%X\n"
+ "\t\t\t\tattr_mod................0x%X\n"
+ "\t\t\t\trmpp_version............0x%X\n"
+ "\t\t\t\trmpp_type...............0x%X\n"
+ "\t\t\t\trmpp_flags..............0x%X\n"
+ "\t\t\t\trmpp_status.............0x%X\n"
+ "\t\t\t\tseg_num.................0x%X\n"
+ "\t\t\t\tpayload_len/new_win.....0x%X\n"
+ "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+ "\t\t\t\tattr_offset.............0x%X\n"
+ "\t\t\t\tresv2...................0x%X\n"
+ "\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n",
+ p_mad->base_ver,
+ p_mad->mgmt_class,
+ p_mad->class_ver,
+ p_mad->method, ib_get_sa_method_str(p_mad->method),
+ cl_ntoh16(p_mad->status),
+ cl_ntoh16(p_mad->resv),
+ cl_ntoh64(p_mad->trans_id),
+ cl_ntoh16(p_mad->attr_id),
+ ib_get_sa_attr_str( p_mad->attr_id ),
+ cl_ntoh16(p_mad->resv1),
+ cl_ntoh32(p_mad->attr_mod),
+ p_mad->rmpp_version,
+ p_mad->rmpp_type,
+ p_mad->rmpp_flags,
+ p_mad->rmpp_status,
+ cl_ntoh32(p_mad->seg_num),
+ cl_ntoh32(p_mad->paylen_newwin),
+ cl_ntoh64(p_mad->sm_key),
+ cl_ntoh16(p_mad->attr_offset),
+ cl_ntoh16(p_mad->resv3),
+ cl_ntoh64(p_mad->comp_mask)
+ );
+
+ strcat( buf, "\n" );
+
+ osm_log( p_log, log_level,
+ "%s\n", buf );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_dr_path(
+ IN osm_log_t* const p_log,
+ IN const osm_dr_path_t* const p_path,
+ IN const osm_log_level_t log_level)
+{
+ uint32_t i;
+ char buf[BUF_SIZE];
+ char line[BUF_SIZE];
+
+ if( osm_log_is_active( p_log, log_level) )
+ {
+ sprintf( buf, "Directed Path Dump of %u hop path:"
+ "\n\t\t\t\tPath = ", p_path->hop_count );
+
+ for( i = 0; i <= p_path->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_path->path[i] );
+ strcat( buf, line );
+ }
+ osm_log( p_log, log_level,
+ "%s\n", buf );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_smp_dr_path(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t log_level
+ )
+{
+ uint32_t i;
+ char buf[BUF_SIZE];
+ char line[BUF_SIZE];
+
+ if( osm_log_is_active( p_log, log_level) )
+ {
+ sprintf( buf, "Received a SMP on a %u hop path:"
+ "\n\t\t\t\tInitial path = ", p_smp->hop_count );
+
+ for( i = 0; i <= p_smp->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_smp->initial_path[i] );
+ strcat( buf, line );
+ }
+
+ strcat( buf, "\n\t\t\t\tReturn path = " );
+
+ for( i = 0; i <= p_smp->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_smp->return_path[i] );
+ strcat( buf, line );
+ }
+
+ osm_log( p_log, log_level,
+ "%s\n", buf );
+ }
+}
+
+const char* const __osm_sm_state_str[] =
+{
+ "OSM_SM_STATE_NO_STATE", /* 0 */
+ "OSM_SM_STATE_INIT", /* 1 */
+ "OSM_SM_STATE_IDLE", /* 2 */
+ "OSM_SM_STATE_SWEEP_LIGHT", /* 3 */
+ "OSM_SM_STATE_SWEEP_LIGHT_WAIT", /* 4 */
+ "OSM_SM_STATE_SWEEP_HEAVY_SELF", /* 5 */
+ "OSM_SM_STATE_SWEEP_HEAVY_SUBNET", /* 6 */
+ "OSM_SM_STATE_SET_SM_UCAST_LID", /* 7 */
+ "OSM_SM_STATE_SET_SM_UCAST_LID_WAIT", /* 8 */
+ "OSM_SM_STATE_SET_SM_UCAST_LID_DONE", /* 9 */
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS", /* 10 */
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT", /* 11 */
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE", /* 12 */
+ "OSM_SM_STATE_SET_UCAST_TABLES", /* 13 */
+ "OSM_SM_STATE_SET_UCAST_TABLES_WAIT", /* 14 */
+ "OSM_SM_STATE_SET_UCAST_TABLES_DONE", /* 15 */
+ "OSM_SM_STATE_SET_MCAST_TABLES", /* 16 */
+ "OSM_SM_STATE_SET_MCAST_TABLES_WAIT", /* 17 */
+ "OSM_SM_STATE_SET_MCAST_TABLES_DONE", /* 18 */
+ "OSM_SM_STATE_SET_LINK_PORTS", /* 19 */
+ "OSM_SM_STATE_SET_LINK_PORTS_WAIT", /* 20 */
+ "OSM_SM_STATE_SET_LINK_PORTS_DONE", /* 21 */
+ "OSM_SM_STATE_SET_ARMED", /* 19 */
+ "OSM_SM_STATE_SET_ARMED_WAIT", /* 20 */
+ "OSM_SM_STATE_SET_ARMED_DONE", /* 21 */
+ "OSM_SM_STATE_SET_ACTIVE", /* 22 */
+ "OSM_SM_STATE_SET_ACTIVE_WAIT", /* 23 */
+ "OSM_SM_STATE_LOST_NEGOTIATION", /* 24 */
+ "OSM_SM_STATE_STANDBY", /* 25 */
+ "OSM_SM_STATE_SUBNET_UP", /* 26 */
+ "OSM_SM_STATE_PROCESS_REQUEST", /* 27 */
+ "OSM_SM_STATE_PROCESS_REQUEST_WAIT", /* 28 */
+ "OSM_SM_STATE_PROCESS_REQUEST_DONE", /* 29 */
+ "OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED", /* 30 */
+ "UNKNOWN STATE!!" /* 31 */
+};
+
+const char* const __osm_sm_signal_str[] =
+{
+ "OSM_SIGNAL_NONE", /* 0 */
+ "OSM_SIGNAL_SWEEP", /* 1 */
+ "OSM_SIGNAL_CHANGE_DETECTED", /* 2 */
+ "OSM_SIGNAL_NO_PENDING_TRANSACTIONS", /* 3 */
+ "OSM_SIGNAL_DONE", /* 4 */
+ "OSM_SIGNAL_DONE_PENDING", /* 5 */
+ "OSM_SIGNAL_LOST_SM_NEGOTIATION", /* 6 */
+ "OSM_SIGNAL_LIGHT_SWEEP_FAIL", /* 7 */
+ "OSM_SIGNAL_IDLE_TIME_PROCESS", /* 8 */
+ "OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST", /* 9 */
+ "OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED", /* 10 */
+ "OSM_SIGNAL_EXIT_STBY", /* 11 */
+ "UNKNOWN SIGNAL!!" /* 12 */
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_state_str(
+ IN osm_sm_state_t state )
+{
+ if( state > OSM_SM_STATE_MAX )
+ state = OSM_SM_STATE_MAX;
+ return( __osm_sm_state_str[state] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_signal_str(
+ IN osm_signal_t signal )
+{
+ if( signal > OSM_SIGNAL_MAX )
+ signal = OSM_SIGNAL_MAX;
+ return( __osm_sm_signal_str[signal] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static const char* const __osm_disp_msg_str[] =
+{
+ "OSM_MSG_REQ",
+ "OSM_MSG_MAD_NODE_INFO",
+ "OSM_MSG_MAD_PORT_INFO,",
+ "OSM_MSG_MAD_SWITCH_INFO",
+ "OSM_MSG_MAD_NODE_DESC",
+ "OSM_MSG_NO_SMPS_OUTSTANDING",
+ "OSM_MSG_MAD_NODE_RECORD",
+ "OSM_MSG_MAD_PORTINFO_RECORD",
+ "OSM_MSG_MAD_SERVICE_RECORD",
+ "OSM_MSG_MAD_PATH_RECORD",
+ "OSM_MSG_MAD_MCMEMBER_RECORD",
+ "OSM_MSG_MAD_LINK_RECORD",
+ "OSM_MSG_MAD_SMINFO_RECORD",
+ "OSM_MSG_MAD_CLASS_PORT_INFO",
+ "OSM_MSG_MAD_INFORM_INFO",
+ "OSM_MSG_MAD_LFT_RECORD",
+ "OSM_MSG_MAD_LFT",
+ "OSM_MSG_MAD_SM_INFO",
+ "OSM_MSG_MAD_NOTICE",
+ "OSM_MSG_LIGHT_SWEEP_FAIL",
+ "OSM_MSG_MAD_MFT",
+ "OSM_MSG_MAD_PKEY_TBL_RECORD",
+ "OSM_MSG_MAD_VL_ARB_RECORD",
+ "OSM_MSG_MAD_SLVL_TBL_RECORD",
+ "OSM_MSG_MAD_PKEY",
+ "OSM_MSG_MAD_VL_ARB",
+ "OSM_MSG_MAD_SLVL",
+ "UNKNOWN!!"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_disp_msg_str(
+ IN cl_disp_msgid_t msg )
+{
+ if( msg > OSM_MSG_MAX )
+ msg = OSM_MSG_MAX;
+ return( __osm_disp_msg_str[msg] );
+}
+
+static const char* const __osm_port_state_str_fixed_width[] =
+{
+ "NOC",
+ "DWN",
+ "INI",
+ "ARM",
+ "ACT",
+ "???"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_port_state_str_fixed_width(
+ IN uint8_t port_state )
+{
+ if( port_state > IB_LINK_ACTIVE )
+ port_state = IB_LINK_ACTIVE + 1;
+ return( __osm_port_state_str_fixed_width[port_state] );
+}
+
+static const char* const __osm_node_type_str_fixed_width[] =
+{
+ "??",
+ "CA",
+ "SW",
+ "RT",
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_node_type_str_fixed_width(
+ IN uint32_t node_type )
+{
+ if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )
+ node_type = 0;
+ return( __osm_node_type_str_fixed_width[node_type] );
+}
+
+#define OSM_VENDOR_ID_INTEL 0x00D0B7
+#define OSM_VENDOR_ID_MELLANOX 0x0002C9
+#define OSM_VENDOR_ID_REDSWITCH 0x000617
+#define OSM_VENDOR_ID_SILVERSTORM 0x00066A
+#define OSM_VENDOR_ID_TOPSPIN 0x0005AD
+#define OSM_VENDOR_ID_FUJITSU 0x00E000
+#define OSM_VENDOR_ID_FUJITSU2 0x000B5D
+#define OSM_VENDOR_ID_VOLTAIRE 0x0008F1
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_manufacturer_str(
+ IN uint64_t const guid_ho )
+{
+ static const char* intel_str = "Intel ";
+ static const char* mellanox_str = "Mellanox ";
+ static const char* redswitch_str = "Redswitch ";
+ static const char* silverstorm_str = "SilverStorm ";
+ static const char* topspin_str = "Topspin ";
+ static const char* fujitsu_str = "Fujitsu ";
+ static const char* voltaire_str = "Voltaire ";
+ static const char* unknown_str = "Unknown ";
+
+ switch( (uint32_t)(guid_ho >> (5 * 8)) )
+ {
+ case OSM_VENDOR_ID_INTEL:
+ return( intel_str );
+ case OSM_VENDOR_ID_MELLANOX:
+ return( mellanox_str );
+ case OSM_VENDOR_ID_REDSWITCH:
+ return( redswitch_str );
+ case OSM_VENDOR_ID_SILVERSTORM:
+ return( silverstorm_str );
+ case OSM_VENDOR_ID_TOPSPIN:
+ return( topspin_str );
+ case OSM_VENDOR_ID_FUJITSU:
+ case OSM_VENDOR_ID_FUJITSU2:
+ return( fujitsu_str );
+ case OSM_VENDOR_ID_VOLTAIRE:
+ return( voltaire_str );
+ default:
+ return( unknown_str );
+ }
+}
+
+static const char* const __osm_mtu_str_fixed_width[] =
+{
+ "??? ",
+ "256 ",
+ "512 ",
+ "1024",
+ "2048",
+ "4096"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_mtu_str(
+ IN uint8_t const mtu )
+{
+ if( mtu > IB_MTU_LEN_4096 )
+ return( __osm_mtu_str_fixed_width[0] );
+ else
+ return( __osm_mtu_str_fixed_width[mtu] );
+}
+
+static const char* const __osm_lwa_str_fixed_width[] =
+{
+ "???",
+ "1x ",
+ "4x ",
+ "???",
+ "???",
+ "???",
+ "???",
+ "???",
+ "12x"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_lwa_str(
+ IN uint8_t const lwa )
+{
+ if( lwa > 8 )
+ return( __osm_lwa_str_fixed_width[0] );
+ else
+ return( __osm_lwa_str_fixed_width[lwa] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const char* const __osm_lsa_str_fixed_width[] =
+{
+ "???",
+ "2.5",
+ "5 ",
+ "???",
+ "10 "
+};
+
+const char*
+osm_get_lsa_str(
+ IN uint8_t const lsa )
+{
+ if( lsa > 4 )
+ return( __osm_lsa_str_fixed_width[0] );
+ else
+ return( __osm_lsa_str_fixed_width[lsa] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+const char* const __osm_sm_mgr_signal_str[] =
+{
+ "OSM_SM_SIGNAL_INIT", /* 0 */
+ "OSM_SM_SIGNAL_DISCOVERY_COMPLETED", /* 2 */
+ "OSM_SM_SIGNAL_POLLING_TIMEOUT", /* 3 */
+ "OSM_SM_SIGNAL_DISCOVER", /* 4 */
+ "OSM_SM_SIGNAL_DISABLE", /* 5 */
+ "OSM_SM_SIGNAL_HANDOVER", /* 6 */
+ "OSM_SM_SIGNAL_HANDOVER_SENT", /* 7 */
+ "OSM_SM_SIGNAL_ACKNOWLEDGE", /* 8 */
+ "OSM_SM_SIGNAL_STANDBY", /* 9 */
+ "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED", /* 10 */
+ "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE", /* 11 */
+ "OSM_SM_SIGNAL_WAIT_FOR_HANDOVER", /* 12 */
+ "UNKNOWN STATE!!" /* 13 */
+
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_mgr_signal_str(
+ IN osm_sm_signal_t signal )
+{
+ if( signal > OSM_SM_SIGNAL_MAX )
+ signal = OSM_SM_SIGNAL_MAX;
+ return( __osm_sm_mgr_signal_str[signal] );
+}
+
+const char* const __osm_sm_mgr_state_str[] =
+{
+ "IB_SMINFO_STATE_NOTACTIVE", /* 0 */
+ "IB_SMINFO_STATE_DISCOVERING", /* 1 */
+ "IB_SMINFO_STATE_STANDBY", /* 2 */
+ "IB_SMINFO_STATE_MASTER", /* 3 */
+ "IB_SMINFO_STATE_INIT", /* 4 */
+ "UNKNOWN STATE!!" /* 5 */
+
+};
+
+const char*
+osm_get_sm_mgr_state_str(
+ IN uint16_t state )
+{
+ if( state > IB_SMINFO_STATE_INIT )
+ state = IB_SMINFO_STATE_INIT + 1;
+ return( __osm_sm_mgr_state_str[state] );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementaion of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <unistd.h>
+#include <complib/cl_timer.h>
+
+static char *month_str[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+};
+#endif /* ndef WIN32 */
+
+void
+osm_log(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_str, ... )
+{
+ char buffer[LOG_ENTRY_SIZE_MAX];
+ va_list args;
+ int ret;
+
+#ifdef WIN32
+ SYSTEMTIME st;
+ uint32_t pid = GetCurrentThreadId();
+#else
+ pid_t pid = 0;
+ time_t tim;
+ struct tm result;
+ uint64_t time_usecs;
+ uint32_t usecs;
+
+ time_usecs = cl_get_time_stamp();
+ tim = time_usecs/1000000;
+ usecs = time_usecs % 1000000;
+ localtime_r(&tim, &result);
+
+#endif /* WIN32 */
+
+ /* If this is a call to syslog - always print it */
+ if ( verbosity & OSM_LOG_SYS )
+ {
+ /* this is a call to the syslog */
+ va_start( args, p_str );
+ vsprintf( buffer, p_str, args );
+ va_end(args);
+ cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
+
+ /* SYSLOG should go to stdout too */
+ if (p_log->out_port != stdout)
+ {
+ printf("%s\n", buffer);
+ fflush( stdout );
+ }
+
+ /* send it also to the log file */
+#ifdef WIN32
+ GetLocalTime(&st);
+ fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+ st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+ pid, buffer);
+#else
+ fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s\n",
+ (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
+ result.tm_mday, result.tm_hour,
+ result.tm_min, result.tm_sec,
+ usecs, pid, buffer);
+ fflush( p_log->out_port );
+#endif
+ }
+
+
+ /* SYS messages go to the log anyways */
+ if (p_log->level & verbosity)
+ {
+#ifdef _MEM_DEBUG_MODE_
+ /* If we are running in MEM_DEBUG_MODE then
+ the cl_mem_check will be called on every run */
+ if (cl_mem_check() == FALSE)
+ {
+ fprintf( p_log->out_port, "*** MEMORY ERROR!!! ***\n" );
+ CL_ASSERT(0);
+ }
+#endif
+
+ va_start( args, p_str );
+ vsprintf( buffer, p_str, args );
+ va_end(args);
+
+ /* regular log to default out_port */
+ cl_spinlock_acquire( &p_log->lock );
+#ifdef WIN32
+ GetLocalTime(&st);
+ ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+ st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+ pid, buffer);
+
+#else
+ pid = pthread_self();
+ tim = time(NULL);
+ ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
+ ((result.tm_mon < 12) && (result.tm_mon >= 0) ?
+ month_str[result.tm_mon] : "???"),
+ result.tm_mday, result.tm_hour,
+ result.tm_min, result.tm_sec,
+ usecs, pid, buffer);
+
+#endif /* WIN32 */
+
+ /*
+ Flush log on errors too.
+ */
+ if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+ fflush( p_log->out_port );
+
+ cl_spinlock_release( &p_log->lock );
+
+ if (ret < 0)
+ {
+ fprintf(stderr, "OSM LOG FAILURE! Probably quota exceeded\n");
+ exit(1);
+ }
+ }
+}
+
+void
+osm_log_raw(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_buf )
+{
+ if( p_log->level & verbosity )
+ {
+ cl_spinlock_acquire( &p_log->lock );
+ printf( "%s", p_buf );
+ cl_spinlock_release( &p_log->lock );
+
+ /*
+ Flush log on errors too.
+ */
+ if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+ fflush( stdout );
+ }
+}
+
+boolean_t
+osm_is_debug(void)
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mad_pool_t.
+ * This object represents a pool of management datagram (MAD) objects.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+
+#define OSM_MAD_POOL_MIN_SIZE 256
+#define OSM_MAD_POOL_GROW_SIZE 256
+
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+__osm_mad_pool_ctor(
+ IN void* const p_object,
+ IN void* context,
+ OUT cl_pool_item_t** const pp_pool_item )
+{
+ osm_madw_t *p_madw = p_object;
+
+ UNUSED_PARAM( context );
+ osm_madw_construct( p_madw );
+ /* CHECK THIS. DOCS DON'T DESCRIBE THIS OUT PARAM. */
+ *pp_pool_item = &p_madw->pool_item;
+ return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_construct(
+ IN osm_mad_pool_t* const p_pool )
+{
+ CL_ASSERT( p_pool );
+
+ cl_memclr( p_pool, sizeof(*p_pool) );
+ cl_qlock_pool_construct( &p_pool->madw_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_destroy(
+ IN osm_mad_pool_t* const p_pool )
+{
+ CL_ASSERT( p_pool );
+
+ /* HACK: we still rarely see some mads leaking - so ignore this */
+ /* cl_qlock_pool_destroy( &p_pool->madw_pool ); */
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mad_pool_init(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status;
+ OSM_LOG_ENTER( p_log, osm_mad_pool_init );
+
+ p_pool->p_log = p_log;
+
+ status = cl_qlock_pool_init(
+ &p_pool->madw_pool,
+ OSM_MAD_POOL_MIN_SIZE,
+ 0,
+ OSM_MAD_POOL_GROW_SIZE,
+ sizeof( osm_madw_t ),
+ __osm_mad_pool_ctor,
+ NULL,
+ p_pool );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_init: ERR 0702: "
+ "Grow pool initialization failed (%s).\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_t *p_madw;
+ ib_mad_t *p_mad;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get );
+
+ CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+ CL_ASSERT( total_size );
+
+ /*
+ Frist, acquire a mad wrapper from the mad wrapper pool.
+ */
+ p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+ if( p_madw == NULL )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get: ERR 0703: "
+ "Unable to acquire MAD wrapper object.\n" );
+ goto Exit;
+ }
+
+ osm_madw_init( p_madw, h_bind, total_size, p_mad_addr );
+
+ /*
+ Next, acquire a wire mad of the specified size.
+ */
+ p_mad = osm_vendor_get( h_bind, total_size, &p_madw->vend_wrap );
+
+ if( p_mad == NULL )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get: ERR 0704: "
+ "Unable to acquire wire MAD.\n" );
+
+ /* Don't leak wrappers! */
+ cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw );
+ p_madw = NULL;
+ goto Exit;
+ }
+
+ cl_atomic_inc( &p_pool->mads_out );
+ /*
+ Finally, attach the wire MAD to this wrapper.
+ */
+ osm_madw_set_mad( p_madw, p_mad );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get: Acquired p_madw = %p, p_mad = %p, "
+ "size = %u.\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const ib_mad_t* const p_mad,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_t *p_madw;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper );
+
+ CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+ CL_ASSERT( total_size );
+ CL_ASSERT( p_mad );
+
+ /*
+ Frist, acquire a mad wrapper from the mad wrapper pool.
+ */
+ p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+ if( p_madw == NULL )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get_wrapper: ERR 0705: "
+ "Unable to acquire MAD wrapper object.\n" );
+ goto Exit;
+ }
+
+ /*
+ Finally, initialize the wrapper object.
+ */
+ cl_atomic_inc( &p_pool->mads_out );
+ osm_madw_init( p_madw, h_bind, total_size, p_mad_addr );
+ osm_madw_set_mad( p_madw, p_mad );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get_wrapper: Acquired p_madw = %p, p_mad = %p "
+ "size = %u\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper_raw(
+ IN osm_mad_pool_t* const p_pool )
+{
+ osm_madw_t *p_madw;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper_raw );
+
+ p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get_wrapper_raw: "
+ "Getting p_madw = %p.\n", p_madw );
+
+ osm_madw_init( p_madw, 0, 0, 0 );
+ osm_madw_set_mad( p_madw, 0 );
+ cl_atomic_inc( &p_pool->mads_out );
+
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_put(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_put );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_put: Releasing p_madw = %p, p_mad = %p.\n",
+ p_madw, p_madw->p_mad );
+
+ /*
+ First, return the wire mad to the pool
+ */
+ if( p_madw->p_mad )
+ osm_vendor_put( p_madw->h_bind, &p_madw->vend_wrap );
+
+ /*
+ Return the mad wrapper to the wrapper pool
+ */
+ cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw );
+ cl_atomic_dec( &p_pool->mads_out );
+
+ OSM_LOG_EXIT( p_pool->p_log );
+}
+
--- /dev/null
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
--- /dev/null
+!if $(FREEBUILD)
+TARGETNAME=osmv_ibal
+!else
+TARGETNAME=osmv_ibald
+!endif
+TARGETTYPE=LIBRARY
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+USE_NTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+ osm_vendor_al.c \
+ osm_vendor_mlx_sa.c \
+ winosm_common.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+ $(LIBPATH)\*\ibal.lib \
+ $(LIBPATH)\*\complib.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+ $(LIBPATH)\*\ibald.lib \
+ $(LIBPATH)\*\complibd.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+ $(OSM_HOME)\include; \
+ $(OSM_HOME); \
+ $(WINIBHOME)\inc; \
+ $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project
+USER_C_FLAGS=$(USER_C_FLAGS) /Ze
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_req_t.
+ * This object represents the generic attribute requester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+/*
+ Next available error code: 0x300
+*/
+#ifdef __WIN__
+/* Suppress all warning regarding casting void* to specific pointer object */
+#pragma warning(disable : 4305)
+#endif
+
+#include <vendor/osm_vendor_select.h>
+
+#ifdef OSM_VENDOR_INTF_AL
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_math.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor_api.h>
+
+/****s* OpenSM: Vendor AL/osm_al_bind_info_t
+ * NAME
+ * osm_al_bind_info_t
+ *
+ * DESCRIPTION
+ * Structure containing bind information.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_al_bind_info
+{
+ osm_vendor_t *p_vend;
+ void *client_context;
+ ib_qp_handle_t h_qp;
+ ib_mad_svc_handle_t h_svc;
+ uint8_t port_num;
+ ib_pool_key_t pool_key;
+ osm_vend_mad_recv_callback_t rcv_callback;
+ osm_vend_mad_send_err_callback_t send_err_callback;
+ osm_mad_pool_t *p_osm_pool;
+ ib_av_handle_t h_dr_av;
+
+} osm_al_bind_info_t;
+/*
+ * FIELDS
+ * p_vend
+ * Pointer to the vendor object.
+ *
+ * client_context
+ * User's context passed during osm_bind
+ *
+ * h_qp
+ * Handle the QP for this bind.
+ *
+ * h_qp_svc
+ * Handle the QP mad service for this bind.
+ *
+ * port_num
+ * Port number (within the HCA) of the bound port.
+ *
+ * pool_key
+ * Pool key returned by all for this QP.
+ *
+ * h_dr_av
+ * Address vector handle used for all directed route SMPs.
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+inline static ib_api_status_t
+__osm_al_convert_wcs(
+ IN ib_wc_status_t const wc_status )
+{
+ switch( wc_status )
+ {
+ case IB_WCS_SUCCESS:
+ return( IB_SUCCESS );
+
+ case IB_WCS_TIMEOUT_RETRY_ERR:
+ return( IB_TIMEOUT );
+
+ default:
+ return( IB_ERROR );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void AL_API
+__osm_set_vend_wrap( IN osm_al_bind_info_t* const p_bind,
+ IN ib_mad_element_t* const p_elem,
+ OUT osm_vend_wrap_t* p_vw)
+{
+ p_vw->h_bind = p_bind;
+ p_vw->size = p_elem->size;
+ p_vw->p_elem = p_elem;
+ p_vw->h_av = 0;
+ p_vw->p_resp_madw = NULL;
+
+}
+
+
+static void AL_API
+__osm_al_ca_err_callback(
+ IN ib_async_event_rec_t *p_async_rec )
+{
+ osm_vendor_t *p_vend = (osm_vendor_t*)p_async_rec->context;
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_err_callback );
+
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_al_ca_err_callback: ERR 3B01: "
+ "Event on channel adapter (%s).\n",
+ ib_get_async_event_str( p_async_rec->code ) );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void AL_API
+__osm_al_ca_destroy_callback(
+ IN void *context )
+{
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)context;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_destroy_callback );
+
+ osm_log( p_vend->p_log, OSM_LOG_INFO,
+ "__osm_al_ca_destroy_callback: "
+ "Closing local channel adapter.\n" );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void AL_API
+__osm_al_err_callback(
+ IN ib_async_event_rec_t *p_async_rec )
+{
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)p_async_rec->context;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_err_callback );
+
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_al_err_callback: ERR 3B02: "
+ "Error on QP (%s).\n",
+ ib_get_async_event_str( p_async_rec->code ) );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ Send_cb will handle the following cases :
+ Element Status | Send Response (no reponse expected) | Send Request (response expeceted)
+ ================|===========================================|==========================================
+ ERROR | Free : AV , madw(send_err_cb) | Free : AV , madw , resp_madw
+ SUCCESS | Free : AV , madw | Free : AV , madw
+
+ Element Status | Receive Response (no reponse expected)
+ ================|===========================================
+ ERROR | Free : AV , madw(send_err_cb)
+ SUCCESS | Free : AV , madw, resp_madw (both through rcv_callback)
+
+*/
+static void AL_API
+__osm_al_send_callback(
+ IN const ib_mad_svc_handle_t h_mad_svc,
+ IN void *mad_svc_context,
+ IN ib_mad_element_t *p_elem )
+{
+ osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
+ osm_vendor_t* const p_vend = p_bind->p_vend;
+ osm_madw_t* const p_madw = (osm_madw_t*)p_elem->context1;
+ osm_vend_wrap_t* p_vw = osm_madw_get_vend_ptr( p_madw );
+ ib_mad_t *p_mad = ib_get_mad_buf( p_elem );
+ ib_av_attr_t av_attr;
+ ib_pd_handle_t h_pd;
+ ib_api_status_t status_elem,status;
+ osm_madw_t *p_new_madw;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_send_callback );
+ UNUSED_PARAM(h_mad_svc);
+ CL_ASSERT( p_vw );
+ CL_ASSERT( p_vw->h_av );
+ /* since we use context1 , safely , and its the only place that remove the clean
+ p_elem,p_madw , h_av no checks are required */
+ status_elem = __osm_al_convert_wcs(p_elem->status);
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_send_callback: "
+ "Destroying av handle %p.\n", p_elem->h_av );
+ /* Check first if its a direct route handle , in this case skip */
+ if (p_elem->h_av != p_bind->h_dr_av)
+ {
+ ib_destroy_av( p_elem->h_av );
+ }
+ /* Since the free order is first resp_madw then madw (PARENT) we should check
+ this case first */
+ if (p_elem->resp_expected)
+ {
+ p_madw->status = status_elem;
+ if ( status_elem != IB_SUCCESS )
+ {
+ /*
+ Return any wrappers to the pool that may have been
+ pre-emptively allocated to handle a receive.
+ */
+ osm_log(p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_al_send_callback: ERR 3333 "
+ " Mad Completed with WQE Error : %s.\n",ib_get_wc_status_str(p_elem->status));
+ if( p_vw->p_resp_madw )
+ {
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+ p_vw->p_resp_madw = NULL;
+ }
+
+ p_bind->send_err_callback( p_bind->client_context, p_madw );
+ }
+ else
+ {
+ /* We are in response flow of receive , need to apply the rcv_callback
+ The rcv_callback will free the resp_madw , req_madw , p_elem of receive
+ and request */
+ osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_send_callback: "
+ "The Mad is a response , thus handeled in __osm_al_send_callback\n");
+ p_new_madw = p_vw->p_resp_madw;
+ p_bind->rcv_callback( p_new_madw, p_bind->client_context,
+ p_madw );
+
+ }
+ }
+ else
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_send_callback: "
+ "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( p_mad->trans_id ) );
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+ if ( status_elem != IB_SUCCESS )
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_al_send_callback: ERR 3b0b "
+ "request mad had failed.\n");
+ goto Exit;
+ }
+
+
+
+
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ Receive_cb will be applied in the following cases :
+ Element Status | Receive Response (no reponse expected) | Receive Request (response expeceted)
+ ================|==============================================|=======================================
+ ERROR | NOT APPLIED | NOT_APPLIED
+ SUCCESS | Free : Resp_madw , copy_req_madw | Allocate new_madw (for response then in send_cb free)
+ */
+ static void AL_API
+__osm_al_rcv_callback(
+ IN const ib_mad_svc_handle_t h_mad_svc,
+ IN void *mad_svc_context,
+ IN ib_mad_element_t *p_elem )
+{
+ osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
+ osm_vendor_t* const p_vend = p_bind->p_vend;
+ osm_madw_t *p_old_madw,*p_copy_old_madw;
+ osm_madw_t *p_new_madw;
+ osm_vend_wrap_t* p_old_vw;
+ osm_vend_wrap_t* p_new_vw;
+ ib_mad_t *p_new_mad;
+ osm_mad_addr_t mad_addr;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_rcv_callback );
+ UNUSED_PARAM(h_mad_svc);
+ CL_ASSERT( p_elem->context1 == NULL );
+ CL_ASSERT( p_elem->context2 == NULL );
+ /*
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+ "__osm_al_rcv_callback: "
+ "Handling Transaction : 0x%" PRIx64 " .\n",
+ cl_ntoh64(p_elem->p_mad_buf->trans_id));
+ */
+ p_new_mad = ib_get_mad_buf( p_elem );
+ /*
+ In preperation for initializing the new mad wrapper,
+ Initialize the mad_addr structure for the received wire MAD.
+ */
+ mad_addr.dest_lid = p_elem->remote_lid;
+ mad_addr.path_bits = p_elem->path_bits;
+
+ /* TO DO - figure out which #define to use for the 2.5 Gb rate... */
+ mad_addr.static_rate = 0;
+
+ if( p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
+ p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR )
+ {
+ mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
+ }
+ else
+ {
+ mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
+ mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
+ mad_addr.addr_type.gsi.pkey = p_elem->pkey_index;
+ mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
+ mad_addr.addr_type.gsi.global_route = FALSE;
+ }
+
+ /*
+ If this MAD is a response to a previous request,
+ then grab our pre-allocated MAD wrapper.
+ Otherwise, allocate a new MAD wrapper.
+ context1 - contains the request madw
+ */
+ if( ib_mad_is_response( p_new_mad ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_rcv_callback: "
+ "The Mad is a response , thus handeled in __osm_al_send_callback\n");
+ CL_ASSERT( p_elem->send_context1 != NULL );
+ CL_ASSERT( p_elem->send_context2 == NULL );
+
+ p_old_madw = (osm_madw_t*)p_elem->send_context1;
+ p_old_vw = osm_madw_get_vend_ptr( p_old_madw );
+ p_new_madw = p_old_vw->p_resp_madw;
+
+ CL_ASSERT( p_new_madw );
+ osm_madw_init( p_new_madw, p_bind, p_elem->size,
+ &mad_addr );
+ osm_madw_set_mad( p_new_madw, p_new_mad );
+ p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
+ __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_rcv_callback: "
+ "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");
+ CL_ASSERT( p_elem->send_context1 == NULL );
+ CL_ASSERT( p_elem->send_context2 == NULL );
+
+ p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,
+ p_bind, p_elem->size, p_new_mad, &mad_addr );
+ CL_ASSERT(p_new_madw);
+ p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
+
+ __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_rcv_callback: "
+ "Calling receive callback function %p.\n",
+ p_bind->rcv_callback );
+
+
+ p_bind->rcv_callback( p_new_madw, p_bind->client_context,
+ ((osm_madw_t*)p_elem->send_context1) );
+ }
+
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_init(
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t* const p_log,
+ IN const uint32_t timeout )
+{
+ ib_api_status_t status;
+ OSM_LOG_ENTER( p_log, osm_vendor_init );
+
+ p_vend->p_log = p_log;
+
+ /*
+ Open our instance of AL.
+ */
+ status = ib_open_al( &p_vend->h_al );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_init: ERR 3B03: "
+ "Error opening AL (%s).\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ p_vend->timeout = timeout;
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_vendor_t*
+osm_vendor_new(
+ IN osm_log_t* const p_log,
+ IN const uint32_t timeout )
+{
+ ib_api_status_t status;
+ osm_vendor_t *p_vend;
+
+ OSM_LOG_ENTER( p_log, osm_vendor_new );
+
+ p_vend = cl_zalloc( sizeof(*p_vend) );
+ if( p_vend == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_new: ERR 3B04: "
+ "Unable to allocate vendor object.\n" );
+ goto Exit;
+ }
+
+ status = osm_vendor_init( p_vend, p_log, timeout );
+ if( status != IB_SUCCESS )
+ {
+ cl_free( p_vend );
+ p_vend = NULL;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( p_vend );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_delete(
+ IN osm_vendor_t** const pp_vend )
+{
+ /* TO DO - fill this in */
+ ib_close_al( (*pp_vend)->h_al );
+ cl_free( *pp_vend );
+ *pp_vend = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_ca_info_init(
+ IN osm_vendor_t* const p_vend,
+ IN osm_ca_info_t* const p_ca_info,
+ IN const ib_net64_t ca_guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );
+
+ p_ca_info->guid = ca_guid;
+
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+ "__osm_ca_info_init: "
+ "Querying CA 0x%" PRIx64 ".\n",
+ cl_ntoh64( ca_guid ) );
+ }
+/* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */
+ status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,
+ &p_ca_info->attr_size );
+ if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_ca_info_init: ERR 3B05: "
+ "Unexpected status getting CA attributes (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_ca_info->attr_size );
+
+ p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );
+ if( p_ca_info->p_attr == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_ca_info_init: ERR 3B06: "
+ "Unable to allocate attribute storage.\n" );
+ goto Exit;
+ }
+
+ status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,
+ (uint32_t*)&p_ca_info->attr_size );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_ca_info_init: ERR 3B07: "
+ "Unexpected status getting CA attributes (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ca_info_destroy(
+ IN osm_vendor_t* const p_vend,
+ IN osm_ca_info_t* const p_ca_info )
+{
+ OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );
+
+ if( p_ca_info->p_attr )
+ cl_free( p_ca_info->p_attr );
+
+ cl_free( p_ca_info );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_ca_info_t*
+osm_ca_info_new(
+ IN osm_vendor_t* const p_vend,
+ IN const ib_net64_t ca_guid )
+{
+ ib_api_status_t status;
+ osm_ca_info_t *p_ca_info;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );
+
+ CL_ASSERT( ca_guid );
+
+ p_ca_info = cl_zalloc( sizeof(*p_ca_info) );
+ if( p_ca_info == NULL )
+ goto Exit;
+
+ status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );
+ if( status != IB_SUCCESS )
+ {
+ osm_ca_info_destroy( p_vend, p_ca_info );
+ p_ca_info = NULL;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( p_ca_info );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_vendor_get_ca_guids(
+ IN osm_vendor_t* const p_vend,
+ IN ib_net64_t** const p_guids,
+ IN size_t* const p_num_guids )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );
+
+ CL_ASSERT( p_guids );
+ CL_ASSERT( p_num_guids );
+
+ status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );
+ if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_get_ca_guids: ERR 3B08: "
+ "Unexpected status getting CA GUID array (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ if( *p_num_guids == 0 )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_get_ca_guids: ERR 3B09: "
+ "No available channel adapters.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );
+ if( *p_guids == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_get_ca_guids: ERR 3B10: "
+ "Unable to allocate CA GUID array.\n" );
+ goto Exit;
+ }
+
+ status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );
+ CL_ASSERT( *p_num_guids );
+
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+ "__osm_vendor_get_ca_guids: "
+ "Detected %u local channel adapters.\n", *p_num_guids );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+/****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
+ * NAME
+ * osm_ca_info_get_pi_ptr
+ *
+ * DESCRIPTION
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ *
+ * SYNOPSIS
+ */
+static ib_port_attr_t*
+__osm_ca_info_get_port_attr_ptr(
+ IN const osm_ca_info_t* const p_ca_info,
+ IN const uint8_t index )
+{
+ return( &p_ca_info->p_attr->p_port_attr[index] );
+}
+/*
+ * PARAMETERS
+ * p_ca_info
+ * [in] Pointer to a CA Info object.
+ *
+ * index
+ * [in] Port "index" for which to retrieve the port attribute.
+ * The index is the offset into the ca's internal array
+ * of port attributes.
+ *
+ * RETURN VALUE
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ * Also allocate p_vend->p_ca_info if not allocated and init it .
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_get_all_port_attr(
+ IN osm_vendor_t* const p_vend,
+ IN ib_port_attr_t* const p_attr_array,
+ IN uint32_t* const p_num_ports )
+{
+ ib_api_status_t status;
+
+ uint32_t ca;
+ size_t ca_count;
+ uint32_t port_count = 0;
+ uint8_t port_num;
+ uint32_t total_ports = 0;
+ ib_net64_t *p_ca_guid = NULL;
+ osm_ca_info_t *p_ca_info;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );
+
+ CL_ASSERT( p_vend );
+
+ /*
+ 1) Determine the number of CA's
+ 2) If not allready allocated - allocate an array big enough to hold the
+ ca info object , the ca info will be overwrite to contain the new ca info
+ 3) Call again to retrieve the guids.
+ */
+ status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );
+
+ if (p_vend->p_ca_info == NULL)
+ {
+ p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );
+
+ if( p_vend->p_ca_info == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_get_all_port_attr: ERR 3B11: "
+ "Unable to allocate CA information array.\n" );
+ goto Exit;
+ }
+ }
+
+ p_vend->ca_count = ca_count;
+
+ /*
+ For each CA, retrieve the port info attributes
+ */
+ for( ca = 0; ca < ca_count; ca++ )
+ {
+ p_ca_info = &p_vend->p_ca_info[ca];
+
+ status = __osm_ca_info_init(
+ p_vend,
+ p_ca_info,
+ p_ca_guid[ca] );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_get_all_port_attr: ERR 3B12: "
+ "Unable to initialize CA Info object (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ total_ports += osm_ca_info_get_num_ports( p_ca_info );
+ }
+
+ /*
+ If the user supplied enough storage, return the port guids,
+ otherwise, return the appropriate error.
+ */
+ if( *p_num_ports >= total_ports )
+ {
+ for( ca = 0; ca < ca_count; ca++ )
+ {
+ uint32_t num_ports;
+
+ p_ca_info = &p_vend->p_ca_info[ca];
+
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );
+
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(
+ p_ca_info, port_num );
+ port_count++;
+ }
+ }
+ }
+ else
+ {
+ status = IB_INSUFFICIENT_MEMORY;
+ }
+
+
+ *p_num_ports = total_ports;
+
+
+ Exit:
+ if( p_ca_guid )
+ cl_free( p_ca_guid );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+osm_vendor_get_ca_guid(
+ IN osm_vendor_t* const p_vend,
+ IN const ib_net64_t port_guid )
+{
+ uint8_t index;
+ uint8_t num_ports;
+ uint32_t num_guids = 0;
+ osm_ca_info_t *p_ca_info;
+ uint32_t ca;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );
+
+ CL_ASSERT( port_guid );
+ /*
+ First, locate the HCA that owns this port.
+ */
+ if( p_vend->p_ca_info == NULL )
+ {
+ /*
+ Initialize the osm_ca_info_t array which allows
+ us to match port GUID to CA.
+ */
+ osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
+ }
+
+ CL_ASSERT( p_vend->p_ca_info );
+ CL_ASSERT( p_vend->ca_count );
+
+ for( ca = 0; ca < p_vend->ca_count; ca++ )
+ {
+ p_ca_info = &p_vend->p_ca_info[ca];
+
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );
+ CL_ASSERT( num_ports );
+
+ for( index = 0; index < num_ports; index++ )
+ {
+ if( port_guid ==
+ osm_ca_info_get_port_guid( p_ca_info, index ) )
+ {
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( osm_ca_info_get_ca_guid( p_ca_info ) );
+ }
+ }
+ }
+
+ /*
+ No local CA owns this guid!
+ */
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_get_ca_guid: ERR 3B13: "
+ "Unable to determine CA guid.\n" );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_vendor_get_port_num(
+ IN osm_vendor_t* const p_vend,
+ IN const ib_net64_t port_guid )
+{
+ uint8_t index;
+ uint8_t num_ports;
+ uint32_t num_guids = 0;
+ osm_ca_info_t *p_ca_info;
+ uint32_t ca;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );
+
+ CL_ASSERT( port_guid );
+ /*
+ First, locate the HCA that owns this port.
+ */
+ if( p_vend->p_ca_info == NULL )
+ {
+ /*
+ Initialize the osm_ca_info_t array which allows
+ us to match port GUID to CA.
+ */
+ osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
+ }
+
+ CL_ASSERT( p_vend->p_ca_info );
+ CL_ASSERT( p_vend->ca_count );
+
+ for( ca = 0; ca < p_vend->ca_count; ca++ )
+ {
+ p_ca_info = &p_vend->p_ca_info[ca];
+
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );
+ CL_ASSERT( num_ports );
+
+ for( index = 0; index < num_ports; index++ )
+ {
+ if( port_guid ==
+ osm_ca_info_get_port_guid( p_ca_info, index ) )
+ {
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( osm_ca_info_get_port_num( p_ca_info, index ) );
+ }
+ }
+ }
+
+ /*
+ No local CA owns this guid!
+ */
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_get_port_num: ERR 3B30: "
+ "Unable to determine CA guid.\n" );
+
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( 0 );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_vendor_open_ca(
+ IN osm_vendor_t* const p_vend,
+ IN const ib_net64_t port_guid )
+{
+ ib_net64_t ca_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );
+
+ ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );
+ if( ca_guid == 0 )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_open_ca: ERR 3B31: "
+ "Bad port GUID value 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+ "__osm_vendor_open_ca: "
+ "Opening HCA 0x%" PRIx64 ".\n", cl_ntoh64( ca_guid ) );
+
+ status = ib_open_ca( p_vend->h_al,
+ ca_guid,
+ __osm_al_ca_err_callback,
+ p_vend,
+ &p_vend->h_ca );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_open_ca: ERR 3B15: "
+ "Unable to open CA (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_vend->h_ca );
+
+ status = ib_alloc_pd(
+ p_vend->h_ca,
+ IB_PDT_ALIAS,
+ p_vend,
+ &p_vend->h_pd );
+
+ if( status != IB_SUCCESS )
+ {
+ ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback );
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osm_vendor_open_ca: ERR 3B16: "
+ "Unable to allocate protection domain (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_vend->h_pd );
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_vendor_init_av(
+ IN const osm_al_bind_info_t* p_bind,
+ IN ib_av_attr_t* p_av )
+{
+ cl_memclr( p_av, sizeof(*p_av) );
+ p_av->port_num = p_bind->port_num;
+ p_av->dlid = IB_LID_PERMISSIVE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_bind_handle_t
+osm_vendor_bind(
+ IN osm_vendor_t* const p_vend,
+ IN osm_bind_info_t* const p_user_bind,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vend_mad_recv_callback_t mad_recv_callback,
+ IN osm_vend_mad_send_err_callback_t send_err_callback,
+ IN void* context )
+{
+ ib_net64_t port_guid;
+ osm_al_bind_info_t *p_bind = 0;
+ ib_api_status_t status;
+ ib_qp_create_t qp_create;
+ ib_mad_svc_t mad_svc;
+ ib_av_attr_t av;
+ DWORD get_last_error;
+ HANDLE handle;
+ char mutex_name[100];
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );
+
+ CL_ASSERT( p_user_bind );
+ CL_ASSERT( p_mad_pool );
+ CL_ASSERT( mad_recv_callback );
+ CL_ASSERT( send_err_callback );
+
+ port_guid = p_user_bind->port_guid;
+ osm_log( p_vend->p_log, OSM_LOG_INFO,
+ "osm_vendor_bind: "
+ "Binding to port 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+
+ if( p_vend->h_ca == 0 )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_bind: "
+ "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));
+
+ status = __osm_vendor_open_ca( p_vend, port_guid );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B17: "
+ "Unable to Open CA (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ p_bind = cl_zalloc( sizeof(*p_bind) );
+ if( p_bind == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B18: "
+ "Unable to allocate internal bind object.\n" );
+ goto Exit;
+ }
+
+ p_bind->p_vend = p_vend;
+ p_bind->client_context = context;
+ p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );
+ p_bind->rcv_callback = mad_recv_callback;
+ p_bind->send_err_callback = send_err_callback;
+ p_bind->p_osm_pool = p_mad_pool;
+
+ CL_ASSERT( p_bind->port_num );
+
+ /* Patch to handle mutiple instances of vendor calls */
+
+ switch( p_user_bind->mad_class )
+ {
+ case IB_MCLASS_SUBN_LID:
+ case IB_MCLASS_SUBN_DIR:
+ sprintf(mutex_name,"Global\\osm_vendor_sm_%d",p_bind->port_num);
+ break;
+
+ case IB_MCLASS_SUBN_ADM:
+ default:
+ sprintf(mutex_name,"Global\\osm_vendor_sa_%d",p_bind->port_num);
+ break;
+ }
+
+
+ handle = CreateMutex( NULL, TRUE, mutex_name);
+
+ if(handle == NULL)
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B32: "
+ "Can't create Mutex\n");
+ cl_free(p_bind);
+ p_bind = NULL;
+ /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
+ exit(1);
+ }
+ get_last_error = GetLastError();
+
+ if (get_last_error == ERROR_ALREADY_EXISTS)
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B35: "
+ "Current Mutex already exist : %s\n",mutex_name);
+ printf("ERROR : Port %d already binded.\n",p_bind->port_num);
+ cl_free(p_bind);
+ p_bind = NULL;
+ /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
+ exit(1);
+ }
+ /* End Of Patch */
+
+ /*
+ Get the proper QP.
+ */
+ cl_memclr( &qp_create, sizeof(qp_create) );
+
+ switch( p_user_bind->mad_class )
+ {
+ case IB_MCLASS_SUBN_LID:
+ case IB_MCLASS_SUBN_DIR:
+ qp_create.qp_type = IB_QPT_QP0_ALIAS;
+ break;
+
+ case IB_MCLASS_SUBN_ADM:
+ default:
+ qp_create.qp_type = IB_QPT_QP1_ALIAS;
+ break;
+ }
+
+ qp_create.sq_depth = p_user_bind->send_q_size;
+ qp_create.rq_depth = p_user_bind->recv_q_size;
+ qp_create.sq_sge = OSM_AL_SQ_SGE;
+ qp_create.rq_sge = OSM_AL_RQ_SGE;
+ status = ib_get_spl_qp(
+ p_vend->h_pd,
+ port_guid,
+ &qp_create,
+ p_bind,
+ __osm_al_err_callback,
+ &p_bind->pool_key,
+ &p_bind->h_qp );
+
+ if( status != IB_SUCCESS )
+ {
+ cl_free( p_bind );
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B19: "
+ "Unable to get QP handle (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_bind->h_qp );
+ CL_ASSERT( p_bind->pool_key );
+
+ cl_memclr( &mad_svc, sizeof(mad_svc) );
+
+ mad_svc.mad_svc_context = p_bind;
+ mad_svc.pfn_mad_send_cb = __osm_al_send_callback;
+ mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
+ mad_svc.mgmt_class = p_user_bind->mad_class;
+ mad_svc.mgmt_version = p_user_bind->class_version;
+ mad_svc.support_unsol = p_user_bind->is_responder;
+ mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
+ mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
+ mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
+ mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
+ mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
+
+
+ status = ib_reg_mad_svc(
+ p_bind->h_qp,
+ &mad_svc,
+ &p_bind->h_svc );
+
+ if( status != IB_SUCCESS )
+ {
+ cl_free( p_bind );
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B21: "
+ "Unable to register QP0 MAD service (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ __osm_vendor_init_av( p_bind, &av );
+
+ status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_bind: ERR 3B22: "
+ "Unable to create address vector (%s).\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_bind: "
+ "Allocating av handle %p.\n", p_bind->h_dr_av );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( (osm_bind_handle_t)p_bind );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging
+ The functionality will be added when the Gen2 osm_vendor_unbind
+ will be implemented.
+*/
+void
+osm_vendor_unbind(
+ IN osm_bind_handle_t h_bind)
+{
+ osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );
+
+ OSM_LOG_EXIT( p_vend->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_mad_t*
+osm_vendor_get(
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t mad_size,
+ IN osm_vend_wrap_t* const p_vw )
+{
+ ib_mad_t *p_mad;
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );
+
+ CL_ASSERT( p_vw );
+
+ p_vw->size = mad_size;
+ p_vw->h_bind = h_bind;
+
+ /*
+ Retrieve a MAD element from the pool and give the user direct
+ access to its buffer.
+ */
+ status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_get: ERR 3B25: "
+ "Unable to acquire MAD (%s).\n",
+ ib_get_err_str( status ) );
+
+ p_mad = NULL;
+ goto Exit;
+ }
+
+ CL_ASSERT( p_vw->p_elem );
+ p_mad = ib_get_mad_buf( p_vw->p_elem );
+
+ if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_get: "
+ "Acquired MAD %p, size = %u.\n", p_mad, mad_size );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( p_mad );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_put(
+ IN osm_bind_handle_t h_bind,
+ IN osm_vend_wrap_t* const p_vw )
+{
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );
+
+ CL_ASSERT( p_vw );
+ CL_ASSERT( p_vw->p_elem );
+ CL_ASSERT( p_vw->h_bind == h_bind );
+
+ if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
+ {
+
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_put: "
+ "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );
+ // "Retiring MAD %p.\n", p_mad);
+ }
+
+ status = ib_put_mad( p_vw->p_elem );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_put: ERR 3B26: "
+ "Unable to retire MAD (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_send(
+ IN osm_bind_handle_t h_bind,
+ IN osm_madw_t* const p_madw,
+ IN boolean_t const resp_expected )
+{
+ osm_al_bind_info_t* const p_bind = h_bind;
+ osm_vendor_t* const p_vend = p_bind->p_vend;
+ osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );
+ osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );
+ ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );
+ ib_api_status_t status;
+ ib_mad_element_t *p_elem;
+ ib_av_attr_t av;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );
+
+ CL_ASSERT( p_vw->h_bind == h_bind );
+ CL_ASSERT( p_vw->p_elem );
+
+ p_elem = p_vw->p_elem;
+
+ /*
+ If a response is expected to this MAD, then preallocate
+ a mad wrapper to contain the wire MAD received in the
+ response. Allocating a wrapper here allows for easier
+ failure paths than after we already received the wire mad.
+ In order to seperate the receive callback and the send callback
+ dependency , we copy the request madw and send it as context2
+ Which in time in the receive callback will replace the req_madw
+ to allow avoid races with send callback
+ */
+ if( resp_expected )
+ {
+ p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(
+ p_bind->p_osm_pool );
+ if( p_vw->p_resp_madw == NULL )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_send: ERR 3B27: "
+ "Unable to allocate MAD wrapper.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ }
+ else
+ p_vw->p_resp_madw = NULL;
+
+ /*
+ For all sends other than directed route SM MADs,
+ acquire an address vector for the destination.
+ */
+ if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )
+ {
+ cl_memclr( &av, sizeof(av) );
+ av.port_num = p_bind->port_num;
+ av.dlid = p_mad_addr->dest_lid;
+ av.static_rate = p_mad_addr->static_rate;
+ av.path_bits = p_mad_addr->path_bits;
+
+ if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
+ (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )
+ {
+ av.sl = p_mad_addr->addr_type.gsi.service_level;
+
+
+ if(p_mad_addr->addr_type.gsi.global_route)
+ {
+ av.grh_valid = TRUE;
+ /* ANIL */
+ /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
+ }
+ }
+
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_send: "
+ "av.port_num 0x%X, "
+ "av.dlid 0x%X, "
+ "av.static_rate %d, "
+ "av.path_bits %d.\n",
+ av.port_num, cl_ntoh16(av.dlid),
+ av.static_rate, av.path_bits);
+ }
+
+ status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_send: ERR 3B28: "
+ "Unable to create address vector (%s).\n",
+ ib_get_err_str( status ) );
+
+ if( p_vw->p_resp_madw )
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+ /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
+ if (p_madw)
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_send: "
+ "Allocating av handle %p.\n", p_vw->h_av );
+ }
+ }
+ else
+ {
+ p_vw->h_av = p_bind->h_dr_av;
+ }
+
+ p_elem->h_av = p_vw->h_av;
+
+ p_elem->context1 = p_madw;
+ p_elem->context2 = NULL;
+
+ p_elem->immediate_data = 0;
+ p_elem->p_grh = NULL;
+ p_elem->resp_expected = resp_expected;
+ p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
+
+ p_elem->send_opt = IB_SEND_OPT_SIGNALED;
+ p_elem->timeout_ms = p_vend->timeout;
+
+ /* Completion information. */
+ p_elem->status = 0; /* Not trusting AL */
+
+
+ if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
+ (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )
+ {
+ p_elem->remote_qp = 0;
+ p_elem->remote_qkey = 0;
+ }
+ else
+ {
+ p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
+ p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
+ osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+ "osm_vendor_send: "
+ "remote qp = 0x%X, remote qkey = 0x%X.\n",
+ cl_ntoh32(p_elem->remote_qp),
+ cl_ntoh32(p_elem->remote_qkey) );
+ }
+
+ status = ib_send_mad( p_bind->h_svc, p_elem, NULL );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_send: ERR 3B29: "
+ "Send failed , cleaning up (%s).\n",
+ ib_get_err_str( status ) );
+ /* When we destroy the av - we should take the pointer from local allocation since
+ we do not "trust" IBAL to keep track in p_elem */
+
+ if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osm_al_send_callback: "
+ "Destroying av handle %p.\n", p_vw->h_av );
+ ib_destroy_av( p_vw->h_av );
+ }
+ if( p_vw->p_resp_madw )
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+ /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
+ if (p_madw)
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_local_lid_change(
+ IN osm_bind_handle_t h_bind )
+{
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ ib_av_attr_t av;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );
+
+ /*
+ The only thing we need to do is refresh the directed
+ route address vector.
+ */
+ __osm_vendor_init_av( p_bind, &av );
+
+ status = ib_destroy_av( p_bind->h_dr_av );
+ p_bind->h_dr_av = NULL;
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_local_lid_change: ERR 3B32: "
+ "Unable to destroy address vector (%s).\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ status = ib_create_av( p_vend->h_pd, &av, &p_bind->h_dr_av );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_local_lid_change: ERR 3B33: "
+ "Unable to create address vector (%s).\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_set_sm(
+ IN osm_bind_handle_t h_bind,
+ IN boolean_t is_sm_val )
+{
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+ osm_vendor_t *p_vend = p_bind->p_vend;
+ ib_api_status_t status;
+ ib_port_attr_mod_t attr_mod;
+
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );
+
+ cl_memclr( &attr_mod, sizeof(attr_mod) );
+
+ attr_mod.cap.sm = is_sm_val;
+
+ status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,
+ IB_CA_MOD_IS_SM, &attr_mod );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "osm_vendor_set_sm: ERR 3B34: "
+ "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
+ is_sm_val, ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_vend->p_log );
+}
+
+#endif /* OSM_VENDOR_INTF_AL */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_timer.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/* this struct is the internal rep of the bind handle */
+typedef struct _osmv_sa_bind_info {
+ osm_bind_handle_t h_bind;
+ osm_log_t *p_log;
+ osm_vendor_t *p_vendor;
+ osm_mad_pool_t *p_mad_pool;
+ uint64_t port_guid;
+ cl_event_t sync_event;
+ uint64_t last_lids_update_sec;
+ uint16_t lid;
+ uint16_t sm_lid;
+} osmv_sa_bind_info_t;
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/*
+ Call back on new mad received:
+
+ We basically only need to set the context of the query.
+ Or report an error.
+
+ A pointer to the actual context of the request (a copy of the oriignal
+ request structure) is attached as the p_madw->context.ni_context.node_guid
+*/
+void
+__osmv_sa_mad_rcv_cb(
+ IN osm_madw_t *p_madw,
+ IN void* bind_context,
+ IN osm_madw_t *p_req_madw)
+{
+ osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context;
+ osmv_query_req_t *p_query_req_copy = NULL;
+ osmv_query_res_t query_res;
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t mad_status;
+
+ OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_rcv_cb );
+
+ if (! p_req_madw)
+ {
+ osm_log( p_bind->p_log, OSM_LOG_DEBUG,
+ "__osmv_sa_mad_rcv_cb: "
+ "Ignoring a non-response mad\n");
+ osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+ goto Exit;
+ }
+
+ /* obtain the sent context */
+ p_query_req_copy =
+ (osmv_query_req_t *)(p_req_madw->context.arb_context.context1);
+
+ /* provide the context of the original request in the result */
+ query_res.query_context = p_query_req_copy->query_context;
+
+ /* provide the resulting madw */
+ query_res.p_result_madw = p_madw;
+
+ /* update the req fields */
+ p_sa_mad = ( ib_sa_mad_t * ) p_madw->p_mad;
+
+ /* if we got a remote error track it in the status */
+ mad_status = ( ib_net16_t ) ( p_sa_mad->status & IB_SMP_STATUS_MASK );
+ if (mad_status != IB_SUCCESS)
+ {
+ osm_log( p_bind->p_log, OSM_LOG_ERROR,
+ "__osmv_sa_mad_rcv_cb: ERR 0501: "
+ "Remote error:0x%04X .\n", mad_status
+ );
+ query_res.status = IB_REMOTE_ERROR;
+ }
+ else
+ {
+ query_res.status = IB_SUCCESS;
+ }
+
+ /* what if we have got back an empty mad ? */
+ if (! p_madw->mad_size)
+ {
+ osm_log( p_bind->p_log, OSM_LOG_ERROR,
+ "__osmv_sa_mad_rcv_cb: ERR 0502: "
+ "Got an empty mad.\n"
+ );
+ query_res.status = IB_ERROR;
+ }
+
+ if (IB_SUCCESS == mad_status)
+ {
+
+ /* if we are in not in a method response of an rmpp nature we must get only 1 */
+ /* HACK: in the future we might need to be smarter for other mathods... */
+ if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ query_res.result_cnt = 1;
+ }
+ else
+ {
+#ifndef VENDOR_RMPP_SUPPORT
+ if (mad_status != IB_SUCCESS)
+ query_res.result_cnt = 0;
+ else
+ query_res.result_cnt = 1;
+#else
+ /* we used the offset value to calculate the number of
+ records in here */
+ query_res.result_cnt =
+ (uintn_t)
+ ( ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) /
+ ib_get_attr_size( p_sa_mad->attr_offset ) );
+ osm_log( p_bind->p_log, OSM_LOG_DEBUG,
+ "__osmv_sa_mad_rcv_cb: Count = %u = %u / %u (%u)\n",
+ query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
+ ib_get_attr_size( p_sa_mad->attr_offset ),
+ ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) %
+ ib_get_attr_size( p_sa_mad->attr_offset )
+ );
+#endif
+ }
+ }
+
+ query_res.query_type = p_query_req_copy->query_type;
+
+ p_query_req_copy->pfn_query_cb( &query_res );
+
+ if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+ cl_event_signal( &p_bind->sync_event );
+
+ Exit:
+
+ /* free the copied query request if found */
+ if (p_query_req_copy) cl_free(p_query_req_copy);
+
+ /* put back the request madw */
+ if (p_req_madw)
+ osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
+
+ OSM_LOG_EXIT( p_bind->p_log );
+}
+
+/*****************************************************************************
+ ****************************************************************************/
+/*
+ Send Error Callback:
+
+ Only report the error and get rid of the mad wrapper
+*/
+void
+__osmv_sa_mad_err_cb(
+ IN void* bind_context,
+ IN osm_madw_t *p_madw)
+{
+ osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context;
+ osmv_query_req_t *p_query_req_copy = NULL;
+ osmv_query_res_t query_res;
+
+ OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_err_cb );
+
+ /* Obtain the sent context etc */
+ p_query_req_copy =
+ (osmv_query_req_t *)(p_madw->context.arb_context.context1);
+
+ /* provide the context of the original request in the result */
+ query_res.query_context = p_query_req_copy->query_context;
+
+ query_res.p_result_madw = p_madw;
+
+ query_res.status = IB_TIMEOUT;
+ query_res.result_cnt = 0;
+
+ query_res.query_type = p_query_req_copy->query_type;
+
+ p_query_req_copy->pfn_query_cb( &query_res );
+
+ if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+ cl_event_signal( &p_bind->sync_event );
+
+ if (p_query_req_copy) cl_free(p_query_req_copy);
+ OSM_LOG_EXIT( p_bind->p_log );
+}
+
+/*****************************************************************************
+ This routine needs to be invoked on every send - since the SM LID and Local
+ lid might change. To do that without any major perfoermance impact we cache
+ the results and time they were obtained. Refresh only twice a minute.
+ To avoid the need to use statics and risk a race - we require the refresh time
+ to be stored in the context of the results. Also this coveres cases were
+ we query for multiple guids.
+ *****************************************************************************/
+ib_api_status_t
+__osmv_get_lid_and_sm_lid_by_port_guid(
+ IN osm_vendor_t* const p_vend,
+ IN ib_net64_t port_guid,
+ IN OUT uint64_t* p_lids_update_time_sec,
+ OUT uint16_t* lid,
+ OUT uint16_t* sm_lid)
+{
+
+ ib_api_status_t status;
+ ib_port_attr_t *p_attr_array;
+ uint32_t num_ports;
+ uint32_t port_num;
+
+ OSM_LOG_ENTER( p_vend->p_log, __osmv_get_lid_and_sm_lid_by_port_guid );
+
+ /* use prevous values if current time is close enough to previous query */
+ if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30)
+ {
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "Using previously stored lid:0x%04x sm_lid:0x%04x\n",
+ *lid, *sm_lid
+ );
+ status = IB_SUCCESS;
+ goto Exit;
+ }
+
+ /* obtain the number of available ports */
+ num_ports = 0;
+ status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
+ if (status != IB_INSUFFICIENT_MEMORY)
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
+ "expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
+ ib_get_err_str(status)
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
+ num_ports, cl_ntoh64(port_guid)
+ );
+
+ /* allocate the attributes */
+ p_attr_array =
+ (ib_port_attr_t *)cl_malloc(sizeof(ib_port_attr_t)*num_ports);
+
+ /* obtain the attributes */
+ status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
+ "Fail to get port attributes (error: %s)\n",
+ ib_get_err_str(status)
+ );
+ cl_free(p_attr_array);
+ goto Exit;
+ }
+
+ status = IB_ERROR;
+ /* find the port requested in the list */
+ for (port_num = 0; (port_num<num_ports) && (status == IB_ERROR); port_num++)
+ {
+ if (p_attr_array[port_num].port_guid == port_guid)
+ {
+ *lid = p_attr_array[port_num].lid;
+ *sm_lid = p_attr_array[port_num].sm_lid;
+ *p_lids_update_time_sec = cl_get_time_stamp_sec();
+ status = IB_SUCCESS;
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "Found guid:0x%016" PRIx64 " with idx:%d\n",
+ cl_ntoh64(port_guid), port_num);
+ }
+ }
+
+ cl_free(p_attr_array);
+
+ Exit:
+ OSM_LOG_EXIT( p_vend->p_log );
+ return ( status );
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+osm_bind_handle_t
+osmv_bind_sa(
+ IN osm_vendor_t* const p_vend,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN ib_net64_t port_guid
+ )
+{
+ osm_bind_info_t bind_info;
+ osm_log_t *p_log = p_vend->p_log;
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_sa_bind_info_t *p_sa_bind_info;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_log, osmv_bind_sa );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_bind_sa: "
+ "Binding to port 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+
+ bind_info.port_guid = port_guid;
+ bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+ bind_info.class_version = 2;
+ bind_info.is_responder = TRUE;
+ bind_info.is_trap_processor = FALSE;
+ bind_info.is_report_processor = TRUE;
+ bind_info.send_q_size = 256;
+ bind_info.recv_q_size = 256;
+
+ /* allocate the new sa bind info */
+ p_sa_bind_info =
+ (osmv_sa_bind_info_t *)cl_malloc(sizeof(osmv_sa_bind_info_t));
+ if (! p_sa_bind_info)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_bind_sa: ERR 0505: "
+ "Fail to allocate new bidn structure\n" );
+ p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+ goto Exit;
+ }
+
+ /* store some important context */
+ p_sa_bind_info->p_log = p_log;
+ p_sa_bind_info->port_guid = port_guid;
+ p_sa_bind_info->p_mad_pool = p_mad_pool;
+ p_sa_bind_info->p_vendor = p_vend;
+ p_sa_bind_info->last_lids_update_sec = 0;
+
+ /* Bind to the lower level */
+ p_sa_bind_info->h_bind =
+ osm_vendor_bind( p_vend,
+ &bind_info,
+ p_mad_pool,
+ __osmv_sa_mad_rcv_cb,
+ __osmv_sa_mad_err_cb,
+ p_sa_bind_info); /* context provided to CBs */
+
+ if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE)
+ {
+ cl_free(p_sa_bind_info);
+ p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_bind_sa: ERR 0506: "
+ "Fail to bind to vendor SMI.\n" );
+ goto Exit;
+ }
+
+ /* obtain the sm_lid from the vendor */
+ status =
+ __osmv_get_lid_and_sm_lid_by_port_guid(
+ p_vend, port_guid,
+ &p_sa_bind_info->last_lids_update_sec,
+ &p_sa_bind_info->lid,
+ &p_sa_bind_info->sm_lid);
+ if (status != IB_SUCCESS)
+ {
+ cl_free(p_sa_bind_info);
+ p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_bind_sa: ERR 0507: "
+ "Fail to obtain the sm lid.\n" );
+ goto Exit;
+ }
+
+ /* initialize the sync_event */
+ cl_event_construct( &p_sa_bind_info->sync_event );
+ cl_status = cl_event_init( &p_sa_bind_info->sync_event, TRUE );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_bind_sa: ERR 0508: "
+ "cl_init_event failed: %s\n",
+ ib_get_err_str(cl_status)
+ );
+ cl_free(p_sa_bind_info);
+ p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return ( p_sa_bind_info );
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/****t* OSM Vendor SA Client/osmv_sa_mad_data
+ * NAME
+ * osmv_sa_mad_data
+ *
+ * DESCRIPTION
+ * Extra fields required to perform a mad query
+ * This struct is passed to the actual send method
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmv_sa_mad_data
+{
+ /* MAD data. */
+ uint8_t method;
+ ib_net16_t attr_id;
+ ib_net16_t attr_offset;
+ ib_net64_t comp_mask;
+ void *p_attr;
+} osmv_sa_mad_data_t;
+/*
+ * method
+ * The method of the mad to be sent
+ *
+ * attr_id
+ * Attribute ID
+ *
+ * attr_offset
+ * Offset as defiend by RMPP
+ *
+ * comp_mask
+ * The component mask of the query
+ *
+ * p_attr
+ * A pointer to the record of the attribute to be sent.
+ *
+ *****/
+
+/*****************************************************************************
+ *****************************************************************************/
+/* Send a MAD out on the GSI interface */
+ib_api_status_t
+__osmv_send_sa_req(
+ IN osmv_sa_bind_info_t* p_bind,
+ IN const osmv_sa_mad_data_t * const p_sa_mad_data,
+ IN const osmv_query_req_t * const p_query_req )
+{
+ ib_api_status_t status;
+ ib_mad_t *p_mad_hdr;
+ ib_sa_mad_t *p_sa_mad;
+ osm_madw_t *p_madw;
+ osm_log_t *p_log = p_bind->p_log;
+ static atomic32_t trans_id;
+ boolean_t sync;
+ osmv_query_req_t *p_query_req_copy;
+
+ OSM_LOG_ENTER( p_log, __osmv_send_sa_req );
+
+ /*
+ since the sm_lid might change we obtain it every send
+ (actually it is cached in the bind object and refreshed
+ every 30sec by this proc )
+ */
+ status =
+ __osmv_get_lid_and_sm_lid_by_port_guid(
+ p_bind->p_vendor, p_bind->port_guid,
+ &p_bind->last_lids_update_sec,
+ &p_bind->lid,
+ &p_bind->sm_lid);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osmv_send_sa_req: ERR 0509: "
+ "Fail to obtain the sm lid.\n" );
+ goto Exit;
+ }
+
+ /* Get a MAD wrapper for the send */
+ p_madw = osm_mad_pool_get(
+ p_bind->p_mad_pool,
+ p_bind->h_bind,
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osmv_send_sa_req: ERR 0510: "
+ "Unable to acquire MAD.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ /* Initialize the Sent MAD: */
+
+ /* Initialize the MAD buffer for the send operation. */
+ p_mad_hdr = osm_madw_get_mad_ptr( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /* Get a new transaction Id */
+ cl_atomic_inc( &trans_id );
+
+ /* Cleanup the MAD from any residue */
+ cl_memclr(p_sa_mad, MAD_BLOCK_SIZE);
+
+ /* Initialize the standard MAD header. */
+ ib_mad_init_new(
+ p_mad_hdr, /* mad pointer */
+ IB_MCLASS_SUBN_ADM, /* class */
+ ( uint8_t ) 2, /* version */
+ p_sa_mad_data->method, /* method */
+ cl_hton64( ( uint64_t ) trans_id ),/* tid */
+ p_sa_mad_data->attr_id, /* attr id */
+ 0 /* attr mod */
+ );
+
+ /* Set the query information. */
+ p_sa_mad->sm_key = p_query_req->sm_key;
+ p_sa_mad->attr_offset = 0;
+ p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
+ if( p_sa_mad->comp_mask )
+ {
+ cl_memcpy( p_sa_mad->data, p_sa_mad_data->p_attr,
+ ib_get_attr_size(p_sa_mad_data->attr_offset));
+ }
+
+ /*
+ Provide the address to send to
+ */
+ /* Patch to handle IBAL - host order , where it should take destination lid in network order */
+#ifdef OSM_VENDOR_INTF_AL
+ p_madw->mad_addr.dest_lid = p_bind->sm_lid;
+#else
+ p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
+#endif
+ p_madw->mad_addr.addr_type.smi.source_lid =
+ cl_hton16(p_bind->lid);
+ p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
+ p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+ p_madw->mad_addr.addr_type.gsi.pkey = IB_DEFAULT_PKEY;
+ p_madw->resp_expected = TRUE;
+ p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+ /*
+ Provide MAD context such that the call back will know what to do.
+ We have to keep the entire request structure so we know the CB.
+ Since we can not rely on the client to keep it arroud until
+ the response - we duplicate it and will later dispose it (in CB).
+ To store on the MADW we cast it into what opensm has:
+ p_madw->context.arb_context.context1
+ */
+ p_query_req_copy = cl_malloc(sizeof(*p_query_req_copy));
+ *p_query_req_copy = *p_query_req;
+ p_madw->context.arb_context.context1 = p_query_req_copy;
+
+ /* we can support async as well as sync calls */
+ sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
+
+ /* send the mad asynchronously */
+ status = osm_vendor_send(
+ osm_madw_get_bind_handle( p_madw ),
+ p_madw,
+ p_madw->resp_expected );
+
+ /* if synchronous - wait on the event */
+ if (sync)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__osmv_send_sa_req: "
+ "Waiting for async event.\n" );
+ cl_event_wait_on( &p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE );
+ cl_event_reset(&p_bind->sync_event);
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return status;
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+/*
+ * Query the SA based on the user's request.
+ */
+ib_api_status_t
+osmv_query_sa(
+ IN osm_bind_handle_t h_bind,
+ IN const osmv_query_req_t * const p_query_req
+ )
+{
+ osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)h_bind;
+ osmv_sa_mad_data_t sa_mad_data;
+ osmv_user_query_t *p_user_query;
+ ib_service_record_t svc_rec;
+ ib_node_record_t node_rec;
+ ib_portinfo_record_t port_info;
+ ib_path_rec_t path_rec;
+ ib_class_port_info_t class_port_info;
+ osm_log_t *p_log = p_bind->p_log;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osmv_query_sa );
+
+ /* Set the request information. */
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+
+ /* Set the MAD attributes and component mask correctly. */
+ switch ( p_query_req->query_type )
+ {
+
+ case OSMV_QUERY_USER_DEFINED:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "USER_DEFINED\n" );
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ if (p_user_query->method) sa_mad_data.method = p_user_query->method;
+ sa_mad_data.attr_offset = p_user_query->attr_offset;
+ sa_mad_data.attr_id = p_user_query->attr_id;
+ sa_mad_data.comp_mask = p_user_query->comp_mask;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ case OSMV_QUERY_ALL_SVC_RECS:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+ sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.comp_mask = 0;
+ sa_mad_data.p_attr = &svc_rec;
+ break;
+
+ case OSMV_QUERY_SVC_REC_BY_NAME:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.p_attr = &svc_rec;
+ cl_memcpy( svc_rec.service_name, p_query_req->p_query_input,
+ sizeof( ib_svc_name_t ) );
+ break;
+
+ case OSMV_QUERY_SVC_REC_BY_ID:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.p_attr = &svc_rec;
+ svc_rec.service_id = *( ib_net64_t * ) ( p_query_req->p_query_input );
+ break;
+
+ case OSMV_QUERY_CLASS_PORT_INFO:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","CLASS_PORT_INFO\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_class_port_info_t ) );
+ sa_mad_data.comp_mask = 0;
+ sa_mad_data.p_attr = &class_port_info;
+
+ break;
+
+ case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","NODE_REC_BY_NODE_GUID\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+ sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_node_record_t ) );
+ sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
+ sa_mad_data.p_attr = &node_rec;
+ node_rec.node_info.node_guid =
+ *( ib_net64_t * ) ( p_query_req->p_query_input );
+
+ break;
+
+ case OSMV_QUERY_PORT_REC_BY_LID:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+ sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
+ sa_mad_data.p_attr = &port_info;
+ port_info.lid = *( ib_net16_t * ) ( p_query_req->p_query_input );
+ break;
+
+ case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID_AND_NUM\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+ sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_vl_arb_table_record_t ) );
+ sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_slvl_table_record_t ) );
+ sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_PORT_GUIDS\n" );
+ cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
+ sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+ sa_mad_data.p_attr = &path_rec;
+ ib_gid_set_default( &path_rec.dgid,
+ ( ( osmv_guid_pair_t * ) ( p_query_req->
+ p_query_input ) )->
+ dest_guid );
+ ib_gid_set_default( &path_rec.sgid,
+ ( ( osmv_guid_pair_t * ) ( p_query_req->
+ p_query_input ) )->
+ src_guid );
+ break;
+
+ case OSMV_QUERY_PATH_REC_BY_GIDS:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_GIDS\n" );
+ cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
+ sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+ sa_mad_data.p_attr = &path_rec;
+ cl_memcpy( &path_rec.dgid,
+ &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+ dest_gid, sizeof( ib_gid_t ) );
+ cl_memcpy( &path_rec.sgid,
+ &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+ src_gid, sizeof( ib_gid_t ) );
+ break;
+
+ case OSMV_QUERY_PATH_REC_BY_LIDS:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_LIDS\n" );
+ cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
+ sa_mad_data.method = IB_MAD_METHOD_GET;
+ sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID );
+ sa_mad_data.p_attr = &path_rec;
+ path_rec.dlid =
+ ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->dest_lid;
+ path_rec.slid =
+ ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->src_lid;
+ break;
+
+ case OSMV_QUERY_UD_MULTICAST_SET:
+ sa_mad_data.method = IB_MAD_METHOD_SET;
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_SET\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ sa_mad_data.comp_mask = p_user_query->comp_mask;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ case OSMV_QUERY_UD_MULTICAST_DELETE:
+ sa_mad_data.method = IB_MAD_METHOD_DELETE;
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_DELETE\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ sa_mad_data.comp_mask = p_user_query->comp_mask;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ default:
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_query_sa DBG:001 %s","UNKNOWN\n" );
+ CL_ASSERT( 0 );
+ return IB_ERROR;
+ }
+
+ status = __osmv_send_sa_req( h_bind, &sa_mad_data, p_query_req );
+
+ OSM_LOG_EXIT( p_log );
+ return status;
+}
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+
--- /dev/null
+#include <vendor/winosm_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+
+int optind=1;
+int opterr=1;
+int optopt='?';
+int iArg=1;
+
+char*
+GetOsmPath(void)
+{
+ char* temp_path;
+ int length;
+ temp_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+ length = GetTempPath(OSM_MAX_LOG_NAME_SIZE,temp_path);
+ if (length > OSM_MAX_LOG_NAME_SIZE)
+ {
+ cl_free(temp_path);
+ temp_path = (char*)cl_malloc(length+1);
+ GetTempPath(length+1,temp_path);
+ }
+ return temp_path;
+}
+/****************************************************************************/
+int getopt_long_only(int argc, char *const*argv,
+ const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+ char chOpt;
+ char tmp_str[256];
+ char* tmp_arg = NULL;
+ char* tok=NULL;
+ int i;
+ char tokens[2] = {'='};
+
+ if (iArg == argc)
+ {
+
+ return (EOF);
+ }
+
+ if (argv[iArg][0] != '-')
+ {
+ /* Does not start with a - - we are done scanning */
+
+ return (EOF);
+ }
+
+ /*termination of scanning */
+ if (!strcmp("--",argv[iArg])) {
+ return EOF;
+
+ }
+
+
+ /* char option : -d 5 */
+ if ((argv[iArg][0] == '-') &&(argv[iArg][1] != '-') ) {
+ optarg = get_char_option(optstring,argv,argc,iArg,&optind,&chOpt);
+ iArg = optind;
+
+ return chOpt;
+ }
+
+ /* Look for this string in longopts */
+ strcpy(tmp_str,&(argv[iArg][2]));
+
+ /*get the option */
+ tok = strtok(tmp_str,tokens);
+
+ for (i = 0; longopts[i].name; i++)
+ {
+ if (strcmp (tok, longopts[i].name) == 0)
+ {
+ /* We have a match */
+ *longindex = i;
+
+ if (longopts[i].flag != NULL) {
+ *(longopts[i].flag) = longopts[i].val;
+ }
+
+
+
+ if (longopts[i].has_arg != no_argument)
+ {
+ /*get the argument */
+
+ if (strchr(argv[iArg],'=') != NULL)
+ {
+ optarg = strtok(NULL,tokens);
+ }else { /*the next arg in cmd line is the param */
+ tmp_arg = argv[iArg+1];
+ if (*tmp_arg == '-') {
+
+ /*no param is found */
+ chOpt = '?';
+ if ((longopts[i].has_arg == required_argument) && opterr)
+ {
+ fprintf (stderr, "Option %s requires argument\n",tok);
+ }
+
+ }else
+ {
+ optarg = tmp_arg;
+ iArg++;
+ optind++;
+ }
+ }
+
+ }/*longopts */
+
+ iArg++;
+ optind++;
+ if (longopts[i].flag == 0)
+ return (longopts[i].val);
+ else return 0;
+
+ }/*end if strcmp */
+ }
+
+ return ('?');
+}
+
+/******************************************************************************/
+static char* get_char_option(const char* optstring,char*const* argv,int argc,
+ int iArg, int* opt_ind,char* opt_p)
+ {
+ char chOpt;
+ char* tmp_str;
+ char* prm = NULL;
+
+ chOpt = argv[iArg][1];
+
+
+ /*non valid argument*/
+ if (!isalpha(chOpt))
+ {
+ chOpt = EOF;
+ goto end;
+ }
+
+ tmp_str = strchr(optstring, chOpt);
+
+ /*the argument wasn't found in optstring */
+ if (tmp_str == NULL){
+ chOpt = EOF;
+ optopt = chOpt;
+ goto end;
+ }
+
+ /* don't need argument */
+ if (tmp_str[1]!= ':' ) {
+ goto end;
+ }
+
+ if (argv[iArg][2] != '\0')
+ {
+ // param is attached to option: -po8889
+ prm = &(argv[iArg][2]);
+ goto end;
+ }
+
+ // must look at next argv for param
+ /*at the end of arg list */
+ if ((iArg)+1 == argc) {
+ /* no param will be found */
+ if (tmp_str[2]== ':' ) {
+ /* optional argument ::*/
+ goto end;
+ }
+ else
+ {
+ chOpt = EOF;
+ goto end;
+ }
+ }
+
+ prm = &(argv[(iArg)+1][0]);
+ if (*prm == '-' )
+ {
+ // next argv is a new option, so param
+ // not given for current option
+ if (tmp_str[2]== ':' ) {
+ /* optional argument ::*/
+ goto end;
+ }
+ else
+ {
+ chOpt = EOF;
+ goto end;
+ }
+ }
+
+ // next argv is the param
+ (*opt_ind)++;
+
+
+end:
+ (*opt_ind)++;
+ *opt_p = chOpt;
+ return prm;
+}
+
+
+/******************************************************************************/
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
--- /dev/null
+!if $(FREEBUILD)
+TARGETNAME=opensm
+!else
+TARGETNAME=opensmd
+!endif
+
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+
+SOURCES=\
+ opensm.rc \
+ osm_db_files.c \
+ osm_db_pack.c \
+ osm_drop_mgr.c \
+ osm_fwd_tbl.c \
+ osm_inform.c \
+ osm_lid_mgr.c \
+ osm_lin_fwd_rcv.c \
+ osm_lin_fwd_rcv_ctrl.c \
+ osm_lin_fwd_tbl.c \
+ osm_link_mgr.c \
+ osm_matrix.c \
+ osm_mcast_fwd_rcv.c \
+ osm_mcast_fwd_rcv_ctrl.c \
+ osm_mcast_mgr.c \
+ osm_mcast_tbl.c \
+ osm_mcm_info.c \
+ osm_mcm_port.c \
+ osm_mtree.c \
+ osm_multicast.c \
+ osm_node.c \
+ osm_node_desc_rcv.c \
+ osm_node_desc_rcv_ctrl.c \
+ osm_node_info_rcv.c \
+ osm_node_info_rcv_ctrl.c \
+ osm_opensm.c \
+ osm_pkey.c \
+ osm_pkey_rcv.c \
+ osm_pkey_rcv_ctrl.c \
+ osm_port.c \
+ osm_port_info_rcv.c \
+ osm_port_info_rcv_ctrl.c \
+ osm_remote_sm.c \
+ osm_req.c \
+ osm_req_ctrl.c \
+ osm_resp.c \
+ osm_sa.c \
+ osm_sa_class_port_info.c \
+ osm_sa_class_port_info_ctrl.c \
+ osm_sa_informinfo.c \
+ osm_sa_informinfo_ctrl.c \
+ osm_sa_lft_record.c \
+ osm_sa_lft_record_ctrl.c \
+ osm_sa_link_record.c \
+ osm_sa_link_record_ctrl.c \
+ osm_sa_mad_ctrl.c \
+ osm_sa_mcmember_record.c \
+ osm_sa_mcmember_record_ctrl.c \
+ osm_sa_node_record.c \
+ osm_sa_node_record_ctrl.c \
+ osm_sa_path_record.c \
+ osm_sa_path_record_ctrl.c \
+ osm_sa_pkey_record.c \
+ osm_sa_pkey_record_ctrl.c \
+ osm_sa_portinfo_record.c \
+ osm_sa_portinfo_record_ctrl.c \
+ osm_sa_response.c \
+ osm_sa_service_record.c \
+ osm_sa_service_record_ctrl.c \
+ osm_sa_slvl_record.c \
+ osm_sa_slvl_record_ctrl.c \
+ osm_sa_sminfo_record.c \
+ osm_sa_sminfo_record_ctrl.c \
+ osm_sa_vlarb_record.c \
+ osm_sa_vlarb_record_ctrl.c \
+ osm_service.c \
+ osm_slvl_map_rcv.c \
+ osm_slvl_map_rcv_ctrl.c \
+ osm_sm.c \
+ osm_sminfo_rcv.c \
+ osm_sminfo_rcv_ctrl.c \
+ osm_sm_mad_ctrl.c \
+ osm_sm_state_mgr.c \
+ osm_state_mgr.c \
+ osm_state_mgr_ctrl.c \
+ osm_subnet.c \
+ osm_sweep_fail_ctrl.c \
+ osm_sw_info_rcv.c \
+ osm_sw_info_rcv_ctrl.c \
+ osm_switch.c \
+ osm_trap_rcv.c \
+ osm_trap_rcv_ctrl.c \
+ osm_ucast_mgr.c \
+ osm_ucast_updn.c \
+ osm_vl15intf.c \
+ osm_vl_arb_rcv.c \
+ osm_vl_arb_rcv_ctrl.c \
+ st.c \
+ main.c \
+ cl_event_wheel.c \
+ cl_dispatcher.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+ $(LIBPATH)\*\ibal.lib \
+ $(LIBPATH)\*\complib.lib \
+ $(TARGETPATH)\*\osmv_ibal.lib \
+ $(TARGETPATH)\*\opensm_ibal.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+ $(LIBPATH)\*\ibald.lib \
+ $(LIBPATH)\*\complibd.lib \
+ $(TARGETPATH)\*\osmv_ibald.lib \
+ $(TARGETPATH)\*\opensm_ibald.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+ $(OSM_HOME)\include; \
+ $(OSM_HOME); \
+ $(WINIBHOME)\inc; \
+ $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of Dispatcher abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/cl_dispatcher.h>
+#include <complib/cl_timer.h>
+
+/* give some guidance when we build our cl_pool of messages */
+#define CL_DISP_INITIAL_MSG_COUNT 256
+#define CL_DISP_MSG_GROW_SIZE 64
+
+
+/* give some guidance when we build our cl_pool of registration elements */
+#define CL_DISP_INITIAL_REG_COUNT 16
+#define CL_DISP_REG_GROW_SIZE 16
+
+
+/********************************************************************
+ __cl_disp_worker
+
+ Description:
+ This function takes messages off the FIFO and calls Processmsg()
+ This function executes as passive level.
+
+ Inputs:
+ p_disp - Pointer to Dispatcher object
+
+ Outputs:
+ None
+
+ Returns:
+ None
+********************************************************************/
+void
+__cl_disp_worker(
+ IN void* context )
+{
+ cl_disp_msg_t *p_msg;
+ cl_dispatcher_t *p_disp = (cl_dispatcher_t*)context;
+
+ cl_spinlock_acquire( &p_disp->lock );
+
+ /* Process the FIFO until we drain it dry. */
+ while( cl_qlist_count( &p_disp->msg_fifo ) )
+ {
+ /* Pop the message at the head from the FIFO. */
+ p_msg = (cl_disp_msg_t*)cl_qlist_remove_head( &p_disp->msg_fifo );
+
+ /* we track the tim ethe last message spent in the queue */
+ p_disp->last_msg_queue_time_us = cl_get_time_stamp() - p_msg->in_time;
+
+ /*
+ * Release the spinlock while the message is processed.
+ * The user's callback may reenter the dispatcher
+ * and cause the lock to be reaquired.
+ */
+ cl_spinlock_release( &p_disp->lock );
+ p_msg->p_dest_reg->pfn_rcv_callback(
+ (void*)p_msg->p_dest_reg->context, (void*)p_msg->p_data );
+
+ cl_atomic_dec( &p_msg->p_dest_reg->ref_cnt );
+
+ /* The client has seen the data. Notify the sender as appropriate. */
+ if( p_msg->pfn_xmt_callback )
+ {
+ p_msg->pfn_xmt_callback( (void*)p_msg->context,
+ (void*)p_msg->p_data );
+ cl_atomic_dec( &p_msg->p_src_reg->ref_cnt );
+ }
+
+ /* Grab the lock for the next iteration through the list. */
+ cl_spinlock_acquire(&p_disp->lock);
+
+ /* Return this message to the pool. */
+ cl_qpool_put( &p_disp->msg_pool, (cl_pool_item_t *)p_msg );
+ }
+
+ cl_spinlock_release( &p_disp->lock );
+}
+
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_construct(
+ IN cl_dispatcher_t* const p_disp )
+{
+ CL_ASSERT( p_disp );
+
+ cl_qlist_init( &p_disp->reg_list );
+ cl_ptr_vector_construct( &p_disp->reg_vec );
+ cl_thread_pool_construct( &p_disp->worker_threads );
+ cl_qlist_init( &p_disp->msg_fifo );
+ cl_spinlock_construct( &p_disp->lock );
+ cl_qpool_construct( &p_disp->msg_pool );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_shutdown(
+ IN cl_dispatcher_t* const p_disp )
+{
+ CL_ASSERT( p_disp );
+
+ /* Stop the thread pool. */
+ cl_thread_pool_destroy( &p_disp->worker_threads );
+
+ /* Process all outstanding callbacks. */
+ __cl_disp_worker( p_disp );
+
+ /* Free all registration info. */
+ while( !cl_is_qlist_empty( &p_disp->reg_list ) )
+ cl_free( cl_qlist_remove_head( &p_disp->reg_list ) );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_destroy(
+ IN cl_dispatcher_t* const p_disp )
+{
+ CL_ASSERT( p_disp );
+
+ cl_spinlock_destroy( &p_disp->lock );
+ /* Destroy the message pool */
+ cl_qpool_destroy( &p_disp->msg_pool );
+ /* Destroy the pointer vector of registrants. */
+ cl_ptr_vector_destroy( &p_disp->reg_vec );
+}
+
+
+/********************************************************************
+ ********************************************************************/
+cl_status_t
+cl_disp_init(
+ IN cl_dispatcher_t* const p_disp,
+ IN const uint32_t thread_count,
+ IN const char* const name )
+{
+ cl_status_t status;
+
+ CL_ASSERT( p_disp );
+
+ cl_disp_construct( p_disp );
+
+ status = cl_spinlock_init( &p_disp->lock );
+ if( status != CL_SUCCESS )
+ {
+ cl_disp_destroy( p_disp );
+ return( status );
+ }
+
+ /* Specify no upper limit to the number of messages in the pool */
+ status = cl_qpool_init( &p_disp->msg_pool, CL_DISP_INITIAL_MSG_COUNT,
+ 0, CL_DISP_MSG_GROW_SIZE, sizeof(cl_disp_msg_t), NULL,
+ NULL, NULL );
+ if( status != CL_SUCCESS )
+ {
+ cl_disp_destroy( p_disp );
+ return( status );
+ }
+
+ status = cl_ptr_vector_init( &p_disp->reg_vec, CL_DISP_INITIAL_REG_COUNT,
+ CL_DISP_REG_GROW_SIZE );
+ if( status != CL_SUCCESS )
+ {
+ cl_disp_destroy( p_disp );
+ return( status );
+ }
+
+ status = cl_thread_pool_init( &p_disp->worker_threads, thread_count,
+ __cl_disp_worker, p_disp, name );
+ if( status != CL_SUCCESS )
+ cl_disp_destroy( p_disp );
+
+ return( status );
+}
+
+
+/********************************************************************
+ ********************************************************************/
+cl_disp_reg_handle_t
+cl_disp_register(
+ IN cl_dispatcher_t* const p_disp,
+ IN const cl_disp_msgid_t msg_id,
+ IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL,
+ IN const void* const context OPTIONAL )
+{
+ cl_disp_reg_info_t *p_reg;
+ cl_status_t status;
+
+ CL_ASSERT( p_disp );
+
+ /* Check that the requested registrant ID is available. */
+ cl_spinlock_acquire( &p_disp->lock );
+ if( (msg_id != CL_DISP_MSGID_NONE ) &&
+ (msg_id < cl_ptr_vector_get_size( &p_disp->reg_vec )) &&
+ (cl_ptr_vector_get( &p_disp->reg_vec, msg_id )) )
+ {
+ cl_spinlock_release( &p_disp->lock );
+ return( NULL );
+ }
+
+ /* Get a registration info from the pool. */
+ p_reg = (cl_disp_reg_info_t*)cl_zalloc( sizeof(cl_disp_reg_info_t) );
+ if( !p_reg )
+ {
+ cl_spinlock_release( &p_disp->lock );
+ return( NULL );
+ }
+
+ p_reg->p_disp = p_disp;
+ p_reg->ref_cnt = 0;
+ p_reg->pfn_rcv_callback = pfn_callback;
+ p_reg->context = context;
+ p_reg->msg_id = msg_id;
+
+ /* Insert the registration in the list. */
+ cl_qlist_insert_tail( &p_disp->reg_list, (cl_list_item_t*)p_reg );
+
+ /* Set the array entry to the registrant. */
+ /* The ptr_vector grow automatically as necessary. */
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ status = cl_ptr_vector_set( &p_disp->reg_vec, msg_id, p_reg );
+ if( status != CL_SUCCESS )
+ {
+ cl_free( p_reg );
+ cl_spinlock_release( &p_disp->lock );
+ return( NULL );
+ }
+ }
+
+ cl_spinlock_release( &p_disp->lock );
+
+ return( p_reg );
+}
+
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_unregister(
+ IN const cl_disp_reg_handle_t handle )
+{
+ cl_disp_reg_info_t *p_reg;
+ cl_dispatcher_t *p_disp;
+
+ if( handle == CL_DISP_INVALID_HANDLE )
+ return;
+
+ p_reg = (cl_disp_reg_info_t*)handle;
+ p_disp = p_reg->p_disp;
+ CL_ASSERT( p_disp );
+
+ cl_spinlock_acquire( &p_disp->lock );
+ /*
+ * Clear the registrant vector entry. This will cause any further
+ * post calls to fail.
+ */
+ if( p_reg->msg_id != CL_DISP_MSGID_NONE )
+ {
+ CL_ASSERT( p_reg->msg_id < cl_ptr_vector_get_size(&p_disp->reg_vec));
+ cl_ptr_vector_set( &p_disp->reg_vec, p_reg->msg_id, NULL );
+ }
+ cl_spinlock_release( &p_disp->lock );
+
+ while( p_reg->ref_cnt > 0)
+ cl_thread_suspend( 1 );
+
+ cl_spinlock_acquire(&p_disp->lock);
+ /* Remove the registrant from the list. */
+ cl_qlist_remove_item( &p_disp->reg_list, (cl_list_item_t*)p_reg );
+ /* Return the registration info to the pool */
+ cl_free( p_reg );
+
+ cl_spinlock_release( &p_disp->lock );
+}
+
+
+/********************************************************************
+ ********************************************************************/
+cl_status_t
+cl_disp_post(
+ IN const cl_disp_reg_handle_t handle,
+ IN const cl_disp_msgid_t msg_id,
+ IN const void* const p_data,
+ IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL,
+ IN const void* const context OPTIONAL )
+{
+ cl_disp_reg_info_t *p_src_reg = (cl_disp_reg_info_t*)handle;
+ cl_disp_reg_info_t *p_dest_reg;
+ cl_dispatcher_t *p_disp;
+ cl_disp_msg_t *p_msg;
+
+ p_disp = handle->p_disp;
+ CL_ASSERT( p_disp );
+ CL_ASSERT( msg_id != CL_DISP_MSGID_NONE );
+
+ cl_spinlock_acquire( &p_disp->lock );
+ /* Check that the recipient exists. */
+ p_dest_reg = cl_ptr_vector_get( &p_disp->reg_vec, msg_id );
+ if( !p_dest_reg )
+ {
+ cl_spinlock_release( &p_disp->lock );
+ return( CL_NOT_FOUND );
+ }
+
+ /* Get a free message from the pool. */
+ p_msg = (cl_disp_msg_t*)cl_qpool_get( &p_disp->msg_pool );
+ if( !p_msg )
+ {
+ cl_spinlock_release( &p_disp->lock );
+ return( CL_INSUFFICIENT_MEMORY );
+ }
+
+ /* Initialize the message */
+ p_msg->p_src_reg = p_src_reg;
+ p_msg->p_dest_reg = p_dest_reg;
+ p_msg->p_data = p_data;
+ p_msg->pfn_xmt_callback = pfn_callback;
+ p_msg->context = context;
+ p_msg->in_time = cl_get_time_stamp();
+
+ /*
+ * Increment the sender's reference count if they request a completion
+ * notification.
+ */
+ if( pfn_callback )
+ cl_atomic_inc( &p_src_reg->ref_cnt );
+
+ /* Increment the recipient's reference count. */
+ cl_atomic_inc( &p_dest_reg->ref_cnt );
+
+ /* Queue the message in the FIFO. */
+ cl_qlist_insert_tail( &p_disp->msg_fifo, (cl_list_item_t *)p_msg );
+ cl_spinlock_release( &p_disp->lock );
+
+ /* Signal the thread pool that there is work to be done. */
+ cl_thread_pool_signal( &p_disp->worker_threads );
+ return( CL_SUCCESS );
+}
+
+void
+cl_disp_get_queue_status(
+ IN const cl_disp_reg_handle_t handle,
+ OUT uint32_t *p_num_queued_msgs,
+ OUT uint64_t *p_last_msg_queue_time_ms)
+{
+ cl_dispatcher_t *p_disp = ((cl_disp_reg_info_t*)handle)->p_disp;
+
+ cl_spinlock_acquire( &p_disp->lock );
+
+ if (p_last_msg_queue_time_ms)
+ *p_last_msg_queue_time_ms = p_disp->last_msg_queue_time_us/1000;
+
+ if (p_num_queued_msgs)
+ *p_num_queued_msgs = cl_qlist_count( &p_disp->msg_fifo );
+
+ cl_spinlock_release( &p_disp->lock );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <math.h>
+#include <complib/cl_debug.h>
+#include <opensm/cl_event_wheel.h>
+
+cl_status_t
+__event_will_age_before(
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ uint64_t aging_time = *((uint64_t*)context);
+ cl_event_wheel_reg_info_t *p_event;
+
+ p_event =
+ PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+ if (p_event->aging_time < aging_time)
+ return CL_SUCCESS;
+ else
+ return CL_NOT_FOUND;
+}
+
+void
+__cl_event_wheel_callback( IN void* context )
+{
+ cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *)context;
+ cl_list_item_t *p_list_item, *p_prev_event_list_item;
+ cl_list_item_t *p_list_next_item;
+ cl_event_wheel_reg_info_t *p_event;
+ uint64_t current_time;
+ uint64_t next_aging_time;
+ uint32_t new_timeout;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, __cl_event_wheel_callback);
+
+ /* might be during closing ... */
+ if (p_event_wheel->closing)
+ {
+ goto JustExit;
+ }
+
+ current_time = cl_get_time_stamp();
+
+ if (NULL != p_event_wheel->p_external_lock) {
+
+ /* Take care of the order of acquiring locks to avoid the deadlock!
+ * The external lock goes first.
+ */
+ CL_SPINLOCK_ACQUIRE(p_event_wheel->p_external_lock);
+ }
+
+ CL_SPINLOCK_ACQUIRE(&p_event_wheel->lock);
+
+ p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+ if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+ {
+ /* the list is empty - nothing to do */
+ goto Exit;
+ }
+
+ /* we found such an item. get the p_event */
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+ while (p_event->aging_time <= current_time)
+ {
+ /* this object has aged - invoke it's callback */
+ if (p_event->pfn_aged_callback)
+ {
+ next_aging_time =
+ p_event->pfn_aged_callback(
+ p_event->key, p_event->num_regs, p_event->context);
+ }
+ else
+ {
+ next_aging_time = 0;
+ }
+
+ /* point to the next object in the wheel */
+ p_list_next_item = cl_qlist_next(p_list_item);
+
+ /* We need to retire the event if the next aging time passed */
+ if (next_aging_time < current_time)
+ {
+ /* remove it from the map */
+ cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item));
+
+ /* pop p_event from the wheel */
+ cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+ /* delete the event info object - allocated by cl_event_wheel_reg */
+ cl_free(p_event);
+ }
+ else
+ {
+ /* update the required aging time */
+ p_event->aging_time = next_aging_time;
+ p_event->num_regs++;
+
+ /* do not remove from the map - but remove from the list head and
+ place in the correct position */
+
+ /* pop p_event from the wheel */
+ cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+ /* find the event that ages just before */
+ p_prev_event_list_item = cl_qlist_find_from_tail(
+ &p_event_wheel->events_wheel,
+ __event_will_age_before,
+ &p_event->aging_time);
+
+ /* insert just after */
+ cl_qlist_insert_next(
+ &p_event_wheel->events_wheel,
+ p_prev_event_list_item ,
+ &p_event->list_item);
+
+ /* as we have modified the list - restart from first item: */
+ p_list_next_item = cl_qlist_head(&p_event_wheel->events_wheel);
+ }
+
+ /* advance to next event */
+ p_list_item = p_list_next_item;
+ if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+ {
+ /* the list is empty - nothing to do */
+ break;
+ }
+
+ /* get the p_event */
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+ }
+
+ /* We need to restart the timer only if the list is not empty now */
+ if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel))
+ {
+ /* get the p_event */
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+ /* start the timer to the timeout [msec] */
+ new_timeout = (uint32_t)(((p_event->aging_time - current_time)/1000)+0.5);
+ osm_log (p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "__cl_event_wheel_callback : "
+ "Restart timer in : %u [msec]\n",
+ new_timeout);
+ cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout);
+ if (cl_status != CL_SUCCESS)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "__cl_event_wheel_callback : ERROR 1000: "
+ "Failed to start timer\n" );
+ }
+ }
+
+ /* release the lock */
+ Exit:
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ if (NULL != p_event_wheel->p_external_lock) {
+ CL_SPINLOCK_RELEASE(p_event_wheel->p_external_lock);
+ }
+ JustExit:
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+/*
+ * Construct and Initialize
+ */
+
+void
+cl_event_wheel_construct(
+ IN cl_event_wheel_t* const p_event_wheel )
+{
+ cl_spinlock_construct( &(p_event_wheel->lock) );
+ cl_timer_construct( &(p_event_wheel->timer) );
+}
+
+cl_status_t
+cl_event_wheel_init(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN osm_log_t *p_log)
+{
+ cl_status_t cl_status = CL_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, cl_event_wheel_init );
+
+ /* initialize */
+ p_event_wheel->p_log = p_log;
+ p_event_wheel->p_external_lock = NULL;
+ p_event_wheel->closing = FALSE;
+ cl_status = cl_spinlock_init( &(p_event_wheel->lock) );
+ if (cl_status != CL_SUCCESS)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_init : ERROR 1000: "
+ "Failed to initialize cl_spinlock\n" );
+ goto Exit;
+ }
+ cl_qlist_init( &p_event_wheel->events_wheel);
+ cl_qmap_init( &p_event_wheel->events_map );
+
+ /* init the timer with timeout */
+ cl_status = cl_timer_init(&p_event_wheel->timer,
+ __cl_event_wheel_callback,
+ p_event_wheel ); /* cb context */
+
+ if (cl_status != CL_SUCCESS)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_init : ERROR 1000: "
+ "Failed to initialize cl_timer\n" );
+ goto Exit;
+ }
+ Exit:
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+ return(cl_status);
+}
+
+cl_status_t
+cl_event_wheel_init_ex(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN osm_log_t *p_log,
+ IN cl_spinlock_t *p_external_lock)
+{
+ cl_status_t cl_status;
+
+ cl_status = cl_event_wheel_init(p_event_wheel, p_log);
+ if (CL_SUCCESS != cl_status)
+ {
+ return cl_status;
+ }
+
+ p_event_wheel->p_external_lock = p_external_lock;
+ return cl_status;
+}
+
+void
+cl_event_wheel_dump(
+ IN cl_event_wheel_t* const p_event_wheel )
+{
+ cl_list_item_t *p_list_item;
+ cl_event_wheel_reg_info_t *p_event;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_dump );
+
+ p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_dump: "
+ "event_wheel ptr:%p \n",
+ p_event_wheel);
+
+ while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) )
+ {
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_dump: "
+ "Found event key:<0x%"PRIx64">, aging time:%" PRIu64".\n",
+ p_event->key, p_event->aging_time );
+ p_list_item = cl_qlist_next( p_list_item );
+ }
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+void
+cl_event_wheel_destroy(
+ IN cl_event_wheel_t* const p_event_wheel )
+{
+ cl_list_item_t *p_list_item;
+ cl_map_item_t *p_map_item;
+ cl_event_wheel_reg_info_t *p_event;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_destroy );
+
+ /* we need to get a lock */
+ CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+
+ cl_event_wheel_dump( p_event_wheel);
+
+ /* go over all the items in the list and remove them */
+ p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel);
+ while ( p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) )
+ {
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_destroy: "
+ "Found outstanding event key:<0x%"PRIx64">.\n",
+ p_event->key );
+
+ /* remove it from the map */
+ p_map_item = &(p_event->map_item);
+ cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item);
+ cl_free(p_event); /* allocated by cl_event_wheel_reg */
+ p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel);
+ }
+
+ /* destroy the timer */
+ cl_timer_destroy( &p_event_wheel->timer );
+
+ /* destroy the lock (this should be done without releasing - we don't want
+ any other run to grab the lock at this point. */
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ cl_spinlock_destroy( &(p_event_wheel->lock) );
+
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+cl_status_t
+cl_event_wheel_reg(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN const uint64_t key,
+ IN const uint64_t aging_time_usec,
+ IN cl_pfn_event_aged_cb_t pfn_callback,
+ IN void* const context )
+{
+ cl_event_wheel_reg_info_t *p_event;
+ uint64_t timeout;
+ cl_status_t cl_status = CL_SUCCESS;
+ cl_list_item_t *prev_event_list_item;
+ cl_map_item_t *p_map_item;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_reg );
+
+ /* Get the lock on the manager */
+ CL_SPINLOCK_ACQUIRE( &(p_event_wheel->lock) );
+
+ cl_event_wheel_dump( p_event_wheel);
+
+ /* Make sure such a key does not exists */
+ p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+ if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+ {
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_reg: "
+ "Already exists key:0x%"PRIx64"\n", key);
+
+ /* already there - remove it from the list as it is getting a new time */
+ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+
+ /* remove the item from the qlist */
+ cl_qlist_remove_item( &p_event_wheel->events_wheel, &p_event->list_item );
+ /* and the qmap */
+ cl_qmap_remove_item( &p_event_wheel->events_map, &p_event->map_item );
+ }
+ else
+ {
+ /* make a new one */
+ p_event = (cl_event_wheel_reg_info_t *)
+ cl_malloc( sizeof (cl_event_wheel_reg_info_t) );
+ p_event->num_regs = 0;
+ }
+
+ p_event->key = key;
+ p_event->aging_time = aging_time_usec;
+ p_event->pfn_aged_callback = pfn_callback;
+ p_event->context = context;
+ p_event->num_regs++;
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_reg: "
+ "Registering event key:0x%"PRIx64" aging in %u [msec].\n",
+ p_event->key,
+ (uint32_t)((p_event->aging_time - cl_get_time_stamp()) / 1000 ));
+
+ /* If the list is empty - need to start the timer */
+ if (cl_is_qlist_empty(&p_event_wheel->events_wheel))
+ {
+ /* Edward Bortnikov 03/29/2003
+ * ++TBD Consider moving the timer manipulation behind the list manipulation.
+ */
+
+ /* calculate the new timeout */
+ timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000;
+
+ /* stop the timer if it is running */
+
+ /* Edward Bortnikov 03/29/2003
+ * Don't call cl_timer_stop() because it spins forever.
+ * cl_timer_start() will invoke cl_timer_stop() by itself.
+ *
+ * The problematic scenario is when __cl_event_wheel_callback()
+ * is in race condition with this code. It sets timer.in_timer_cb
+ * to TRUE and then blocks on p_event_wheel->lock. Following this,
+ * the call to cl_timer_stop() hangs. Following this, the whole system
+ * enters into a deadlock.
+ *
+ * cl_timer_stop(&p_event_wheel->timer);
+ */
+
+ /* The timeout for the cl_timer_start should be given as uint32_t.
+ if there is an overflow - warn about it. */
+ if ( timeout > (uint32_t)timeout )
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_INFO,
+ "cl_event_wheel_reg: "
+ "timeout requested is too large. Using timeout: %u \n",
+ (uint32_t)timeout );
+ }
+
+ /* start the timer to the timeout [msec] */
+ cl_status = cl_timer_start(&p_event_wheel->timer, (uint32_t)timeout);
+
+ if (cl_status != CL_SUCCESS)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_reg : ERROR 1000: "
+ "Failed to start timer\n" );
+ goto Exit;
+ }
+ }
+
+ /* insert the object to the qlist and the qmap */
+
+ /* BUT WE MUST INSERT IT IN A SORTED MANNER */
+ prev_event_list_item = cl_qlist_find_from_tail(
+ &p_event_wheel->events_wheel,
+ __event_will_age_before,
+ &p_event->aging_time);
+
+ cl_qlist_insert_next(
+ &p_event_wheel->events_wheel,
+ prev_event_list_item ,
+ &p_event->list_item);
+
+ cl_qmap_insert( &p_event_wheel->events_map, key, &(p_event->map_item));
+
+ Exit:
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+
+ return cl_status;
+}
+
+void
+cl_event_wheel_unreg(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN uint64_t key )
+{
+ cl_event_wheel_reg_info_t *p_event;
+ cl_map_item_t* p_map_item;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_unreg );
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_unreg: "
+ "Removing key:0x%"PRIx64".\n", key );
+
+ CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+ p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+ if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+ {
+ /* we found such an item. */
+ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+
+ /* remove the item from the qlist */
+ cl_qlist_remove_item( &p_event_wheel->events_wheel, &(p_event->list_item));
+ /* remove the item from the qmap */
+ cl_qmap_remove_item( &p_event_wheel->events_map, &(p_event->map_item) );
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_unreg: "
+ "Removed key:0x%"PRIx64".\n", key );
+
+ /* free the item */
+ cl_free(p_event);
+ }
+ else
+ {
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_unreg: "
+ "Did not find key:0x%"PRIx64"\n", key );
+ }
+
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+
+}
+
+uint32_t
+cl_event_wheel_num_regs(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN uint64_t key )
+{
+
+ cl_event_wheel_reg_info_t *p_event;
+ cl_map_item_t* p_map_item;
+ uint32_t num_regs = 0;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_num_regs );
+
+ /* try to find the key in the map */
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_num_regs: "
+ "Looking for key:0x%"PRIx64".\n", key );
+
+ CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+ p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+ if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+ {
+ /* ok so we can simply return it's num_regs */
+ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+ num_regs = p_event->num_regs;
+ }
+
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+ return(num_regs);
+}
+
+#ifdef __CL_EVENT_WHEEL_TEST__
+
+/* Dump out the complete state of the event wheel */
+void __cl_event_wheel_dump(
+ IN cl_event_wheel_t* const p_event_wheel)
+{
+ cl_list_item_t *p_list_item;
+ cl_map_item_t *p_map_item;
+ cl_event_wheel_reg_info_t *p_event;
+
+ printf("************** Event Wheel Dump ***********************\n");
+ printf("Event Wheel List has %u items:\n",
+ cl_qlist_count( &p_event_wheel->events_wheel ));
+
+ p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+ while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel))
+ {
+ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+ printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n",
+ p_event->key, (char *)p_event->context, p_event->num_regs);
+
+ /* next */
+ p_list_item = cl_qlist_next(p_list_item);
+ }
+
+ printf("Event Map has %u items:\n",
+ cl_qmap_count( &p_event_wheel->events_map ));
+
+ p_map_item = cl_qmap_head(&p_event_wheel->events_map);
+ while (p_map_item != cl_qmap_end(&p_event_wheel->events_map))
+ {
+ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+ printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n",
+ p_event->key, (char *)p_event->context, p_event->num_regs);
+
+ /* next */
+ p_map_item = cl_qmap_next(p_map_item);
+ }
+
+}
+
+/* The callback for aging event */
+/* We assume we pass a text context */
+void __test_event_aging(uint64_t key, void *context)
+{
+ printf("*****************************************************\n");
+ printf("Aged key: 0x%"PRIx64" Conetxt:%s\n", key, (char *)context);
+}
+
+int
+main ()
+{
+ osm_log_t log;
+ cl_event_wheel_t event_wheel;
+ /* uint64_t key; */
+
+ /* construct */
+ osm_log_construct( &log );
+ cl_event_wheel_construct( &event_wheel );
+
+ /* init */
+ osm_log_init( &log, TRUE, 0xff, NULL);
+ cl_event_wheel_init( &event_wheel, &log );
+
+ /* Start Playing */
+ cl_event_wheel_reg( &event_wheel,
+ 1, /* key */
+ cl_get_time_stamp() + 3000000, /* 3 sec lifetime */
+ __test_event_aging, /* cb */
+ "The first Aging Event"
+ );
+
+ cl_event_wheel_reg( &event_wheel,
+ 2, /* key */
+ cl_get_time_stamp() + 3000000, /* 3 sec lifetime */
+ __test_event_aging, /* cb */
+ "The Second Aging Event"
+ );
+
+ cl_event_wheel_reg( &event_wheel,
+ 3, /* key */
+ cl_get_time_stamp() + 3500000, /* 3 sec lifetime */
+ __test_event_aging, /* cb */
+ "The Third Aging Event"
+ );
+
+ __cl_event_wheel_dump(&event_wheel);
+
+ sleep(2);
+ cl_event_wheel_reg( &event_wheel,
+ 2, /* key */
+ cl_get_time_stamp() + 8000000, /* 3 sec lifetime */
+ __test_event_aging, /* cb */
+ "The Second Aging Event Moved"
+ );
+
+ __cl_event_wheel_dump(&event_wheel);
+
+ sleep(1);
+ /* remove the third event */
+ cl_event_wheel_unreg( &event_wheel,
+ 3); /* key */
+
+ /* get the number of registrations for the keys */
+ printf("Event 1 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 1));
+ printf("Event 2 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 2));
+
+ sleep(5);
+ /* destroy */
+ cl_event_wheel_destroy( &event_wheel );
+
+ return(0);
+}
+
+#endif /* __CL_EVENT_WHEEL_TEST__ */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id: main.c 3445 2005-09-15 08:35:44Z yael $
+ */
+
+
+/*
+ * Abstract:
+ * Command line interface for opensm.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.23 $
+ */
+#pragma warning(disable : 4996)
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include "stdio.h"
+#include <stdlib.h>
+#include <complib/cl_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_ucast_updn.h>
+
+/********************************************************************
+ D E F I N E G L O B A L V A R I A B L E S
+*********************************************************************/
+/*
+ This is the global opensm object.
+ One opensm object is required per subnet.
+ Future versions could support multiple subents by
+ instantiating more than one opensm object.
+*/
+osm_opensm_t osm;
+volatile int osm_exit_flag = 0;
+
+#define GUID_ARRAY_SIZE 64
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage(void)
+{
+ printf( "\n------- OpenSM - Usage and options ----------------------\n" );
+ printf( "Usage: opensm [options]\n");
+ printf( "Options:\n" );
+ printf( "-c\n"
+ "--cache-options\n"
+ " Cache the given command line options into the file\n"
+ " /var/cache/osm/opensm.opts for use next invocation\n"
+ " The cache directory can be changed by the environment\n"
+ " variable OSM_CACHE_DIR\n\n");
+ printf( "-g <GUID in hex>\n"
+ "--guid <GUID in hex>\n"
+ " This option specifies the local port GUID value\n"
+ " with which OpenSM should bind. OpenSM may be\n"
+ " bound to 1 port at a time.\n"
+ " If GUID given is 0, OpenSM displays a list\n"
+ " of possible port GUIDs and waits for user input.\n"
+ " Without -g, OpenSM trys to use the default port.\n\n");
+ printf( "-l <LMC>\n"
+ "--lmc <LMC>\n"
+ " This option specifies the subnet's LMC value.\n"
+ " The number of LIDs assigned to each port is 2^LMC.\n"
+ " The LMC value must be in the range 0-7.\n"
+ " LMC values > 0 allow multiple paths between ports.\n"
+ " LMC values > 0 should only be used if the subnet\n"
+ " topology actually provides multiple paths between\n"
+ " ports, i.e. multiple interconnects between switches.\n"
+ " Without -l, OpenSM defaults to LMC = 0, which allows\n"
+ " one path between any two ports.\n\n" );
+ printf( "-p <PRIORITY>\n"
+ "--priority <PRIORITY>\n"
+ " This option specifies the SM's PRIORITY.\n"
+ " This will effect the handover cases, where master\n"
+ " is chosen by priority and GUID.\n" );
+ printf( "-r\n"
+ "--reassign_lids\n"
+ " This option causes OpenSM to reassign LIDs to all\n"
+ " end nodes. Specifying -r on a running subnet\n"
+ " may disrupt subnet traffic.\n"
+ " Without -r, OpenSM attempts to preserve existing\n"
+ " LID assignments resolving multiple use of same LID.\n\n");
+ printf( "-u\n"
+ "--updn\n"
+ " This option activate UPDN algorithm instead of Min Hop\n"
+ " algorithm (default).\n");
+ printf ("-a\n"
+ "--add_guid_file <path to file>\n"
+ " Set the root nodes for the Up/Down routing algorithm\n"
+ " to the guids provided in the given file (one at a line)\n"
+ "\n");
+ printf( "-o\n"
+ "--once\n"
+ " This option causes OpenSM to configure the subnet\n"
+ " once, then exit. Ports remain in the ACTIVE state.\n" );
+ printf( "-s <interval>\n"
+ "--sweep <interval>\n"
+ " This option specifies the number of seconds between\n"
+ " subnet sweeps. Specifying -s 0 disables sweeping.\n"
+ " Without -s, OpenSM defaults to a sweep interval of\n"
+ " 10 seconds.\n\n" );
+ printf( "-t <milliseconds>\n"
+ "--timeout <milliseconds>\n"
+ " This option specifies the time in milliseconds\n"
+ " used for transaction timeouts.\n"
+ " Specifying -t 0 disables timeouts.\n"
+ " Without -t, OpenSM defaults to a timeout value of\n"
+ " 100 milliseconds.\n\n" );
+ printf( "-maxsmps <number>\n"
+ " This option specifies the number of VL15 SMP MADs\n"
+ " allowed on the wire at any one time.\n"
+ " Specifying -maxsmps 0 allows unlimited outstanding\n"
+ " SMPs.\n"
+ " Without -maxsmps, OpenSM defaults to a maximum of\n"
+ " one outstanding SMP.\n\n" );
+ printf( "-i <equalize-ignore-guids-file>\n"
+ "-ignore-guids <equalize-ignore-guids-file>\n"
+ " This option provides means to define a set of ports\n"
+ " (by guids) that will be ignored by the link load \n"
+ " equalization algorithm.\n\n" );
+ printf( "-f\n"
+ "--log_file\n"
+ " This option defines the log to be the given file.\n"
+ " By default the log goes to /var/log/osm.log.\n"
+ " For the log to go to standard output use -f stdout.\n\n");
+ printf( "-v\n"
+ "--verbose\n"
+ " This option increases the log verbosity level.\n"
+ " The -v option may be specified multiple times\n"
+ " to further increase the verbosity level.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-V\n"
+ " This option sets the maximum verbosity level and\n"
+ " forces log flushing.\n"
+ " The -V is equivalent to '-vf 0xFF -d 2'.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-D <flags>\n"
+ " This option sets the log verbosity level.\n"
+ " A flags field must follow the -D option.\n"
+ " A bit set/clear in the flags enables/disables a\n"
+ " specific log level as follows:\n"
+ " BIT LOG LEVEL ENABLED\n"
+ " ---- -----------------\n"
+ " 0x01 - ERROR (error messages)\n"
+ " 0x02 - INFO (basic messages, low volume)\n"
+ " 0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+ " 0x08 - DEBUG (diagnostic, high volume)\n"
+ " 0x10 - FUNCS (function entry/exit, very high volume)\n"
+ " 0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+ " 0x40 - ROUTING (dump FDB routing information)\n"
+ " 0x80 - currently unused.\n"
+ " Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
+ " Specifying -D 0 disables all messages.\n"
+ " Specifying -D 0xFF enables all messages (see -V).\n"
+ " High verbosity levels may require increasing\n"
+ " the transaction timeout with the -t option.\n\n" );
+ printf( "-d <number>\n"
+ "--debug <number>\n"
+ " This option specifies a debug option.\n"
+ " These options are not normally needed.\n"
+ " The number following -d selects the debug\n"
+ " option to enable as follows:\n"
+ " OPT Description\n"
+ " --- -----------------\n"
+ " -d0 - Ignore other SM nodes.\n"
+ " -d1 - Force single threaded dispatching.\n"
+ " -d2 - Force log flushing after each log message.\n"
+ " -d3 - Disable multicast support.\n"
+ " -d4 - Put OpenSM in memory tracking mode.\n"
+ " -d10.. Put OpenSM in testability mode.\n"
+ " Without -d, no debug options are enabled.\n\n" );
+ printf( "-h\n"
+ "--help\n"
+ " Display this usage info then exit.\n\n" );
+ printf( "-?\n"
+ " Display this usage info then exit.\n\n" );
+ fflush( stdout );
+ osm_exit_flag = 1;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu(void)
+{
+ printf("\n------- Interactive Menu -------\n");
+ printf("X - Exit.\n\n");
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+get_port_guid(
+ IN osm_opensm_t *p_osm, uint64_t port_guid )
+{
+ uint32_t i;
+ uint32_t choice = 0;
+ char junk[128];
+ boolean_t done_flag = FALSE;
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+ /*
+ Call the transport layer for a list of local port
+ GUID values.
+ */
+ status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports );
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from osm_opensm_init (%x)\n", status);
+ return( 0 );
+ }
+
+ /* if num_ports is 0 - return 0 */
+ if( num_ports == 0 )
+ {
+ printf( "\nNo local ports detected!\n" );
+ return( 0 );
+ }
+ /* If num_ports is 1, then there is only one possible port to use. Use it. */
+ if ( num_ports == 1 )
+ {
+ printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+ return( attr_array[0].port_guid );
+ }
+
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
+ if ( port_guid == 0 )
+ {
+ printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+ return( attr_array[0].port_guid );
+ }
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ /* More than one possible port - list all ports and let the user to choose. */
+ while( done_flag == FALSE )
+ {
+ printf( "\nChoose a local port number with which to bind:\n\n" );
+ /* If this is gen2 code - then port 0 has details of the default port used.
+ no need to print it.
+ If this is not gen2 code - need to print details of all ports. */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ for( i = 1; i < num_ports; i++ )
+ {
+ printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+ i, cl_ntoh64( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i-1 );
+# else
+ for( i = 0; i < num_ports; i++ )
+ {
+ /*
+ Print the index + 1 since by convention, port numbers
+ start with 1 on host channel adapters.
+ */
+
+ printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+ i+1, cl_ntoh64( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ fflush( stdout );
+ if (scanf( "%u", &choice ))
+ {
+ /* If gen2 code - choice can be between 1 to num_ports-1
+ if not gen2 code - choice can be between 1 to num_ports */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ if( choice >= num_ports )
+# else
+ if( choice > num_ports || choice < 1 )
+#endif /* OSM_VENDOR_INTF_OPENIB */
+ {
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ else
+ {
+ done_flag = TRUE;
+ }
+ }
+ else
+ {
+ /* get rid of the junk in the selection line */
+ scanf( "%s", junk );
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ }
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));
+ return( attr_array[choice].port_guid );
+# else
+ return( attr_array[choice - 1].port_guid );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+}
+
+/**********************************************************************
+ **********************************************************************/
+#define OSM_MAX_IGNORE_GUID_LINES_LEN 128
+int
+parse_ignore_guids_file(IN char *guids_file_name,
+ IN osm_opensm_t *p_osm)
+{
+ FILE *fh;
+ char line[OSM_MAX_IGNORE_GUID_LINES_LEN];
+ char *p_c, *p_ec;
+ uint32_t line_num = 0;
+ uint64_t port_guid;
+ ib_api_status_t status = IB_SUCCESS;
+ unsigned int port_num;
+ OSM_LOG_ENTER( &p_osm->log, parse_ignore_guids_file );
+
+ fh = fopen( guids_file_name, "r" );
+ if( fh == NULL )
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0601: "
+ "Unable to open ignore guids file (%s).\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Parse the file and add to the ignore guids map.
+ */
+ while( fgets( line, OSM_MAX_IGNORE_GUID_LINES_LEN, fh ) != NULL )
+ {
+ line_num++;
+ p_c = line;
+ while ( (*p_c == ' ') && (*p_c != '\0')) p_c++ ;
+ port_guid = cl_hton64( strtoull( p_c, &p_ec, 16 ) );
+ if (p_ec == p_c)
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0602: "
+ "Error in line (%u): %s" ,
+ line_num, line
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ while ( (*p_ec == ' ') && (*p_ec != '\0')) p_ec++ ;
+ if (! sscanf(p_ec, "%d", &port_num))
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0603: "
+ "Error in line (%u): %s" ,
+ line_num, p_ec
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ /* Make sure the port_num isn't greater than 256 */
+ if (port_num > 256)
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR XXX: "
+ "Error in line (%u): %s. "
+ "port number is greater than 256 (%d) \n",
+ line_num, p_ec, port_num
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ /* ok insert it */
+ osm_port_pro_set_ignored_port(&p_osm->subn, port_guid, (uint8_t)port_num);
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "parse_ignore_guids_file: "
+ "Inserted Port: 0x%" PRIx64 " into ignored guids list\n" ,
+ port_guid
+ );
+
+ }
+
+ fclose( fh );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osm->log );
+ return ( status );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+int __cdecl
+main(
+ int argc,
+ char* argv[] )
+{
+ osm_subn_opt_t opt;
+ ib_net64_t guid = 0;
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_DEFAULT_LEVEL;
+ int long temp;
+ uint32_t dbg_lvl;
+ boolean_t run_once_flag = FALSE;
+ boolean_t mem_track = FALSE;
+ uint32_t next_option;
+ uint32_t exitTimeout;
+ boolean_t cache_options = FALSE;
+ char *ignore_guids_file_name = NULL;
+ uint32_t val;
+ const char * const short_option = "i:f:d:g:l:s:t:vVhorc";
+
+ /*
+ In the array below, the 2nd parameter specified the number
+ of arguments as follows:
+ 0: no arguments
+ 1: argument
+ 2: optional
+ */
+ const struct option long_option[] =
+ {
+ { "debug", 1, NULL, 'd'},
+ { "guid", 1, NULL, 'g'},
+ { "ignore_guids", 1, NULL, 'i'},
+ { "lmc", 1, NULL, 'l'},
+ { "sweep", 1, NULL, 's'},
+ { "timeout", 1, NULL, 't'},
+ { "verbose", 0, NULL, 'v'},
+ { "D", 1, NULL, 'D'},
+ { "log_file", 1, NULL, 'f'},
+ { "maxsmps", 1, NULL, 'n'},
+ { "V", 0, NULL, 'V'},
+ { "help", 0, NULL, 'h'},
+ { "once", 0, NULL, 'o'},
+ { "reassign_lids", 0, NULL, 'r'},
+ { "priority", 1, NULL, 'p'},
+ { "updn", 0, NULL, 'u'},
+ { "add_guid_file", 1, NULL, 'a'},
+ { "cache-options", 0, NULL, 'c'},
+ { NULL, 0, NULL, 0 } /* Required at the end of the array */
+ };
+
+ printf("-------------------------------------------------\n");
+ printf("%s\n", OSM_VERSION);
+
+ osm_subn_set_default_opt(&opt);
+ osm_subn_parse_conf_file(&opt);
+
+ printf("Command Line Arguments:\n");
+ do
+ {
+ next_option = getopt_long_only(argc, argv, short_option,
+ long_option, NULL);
+ switch(next_option)
+ {
+ case 'o':
+ /*
+ Run once option.
+ */
+ run_once_flag = TRUE;
+ printf(" Run Once\n");
+ break;
+
+ case 'r':
+ /*
+ Reassign LIDs subnet option.
+ */
+ opt.reassign_lids = TRUE;
+ printf(" Reassign LIDs\n");
+ break;
+
+ case 'i':
+ /*
+ Specifies ignore guids file.
+ */
+ ignore_guids_file_name = optarg;
+ printf(" Ignore Guids File = %s\n", ignore_guids_file_name);
+ break;
+
+ case 'g':
+ /*
+ Specifies port guid with which to bind.
+ */
+ guid = cl_hton64( strtoull( optarg, NULL, 16 ));
+ if (! guid)
+ {
+ /* If guid is 0 - need to display the guid list */
+ guid = INVALID_GUID;
+ }
+ else
+ printf(" Guid <0x%"PRIx64">\n", cl_hton64( guid ));
+ break;
+
+ case 's':
+ val = strtol(optarg, NULL, 0);
+ /* Check that the number is not too large */
+ if ( ((uint32_t)(val * 1000000)) / 1000000 != val )
+ fprintf(stderr, "ERROR: sweep interval given is too large. Ignoring it.\n");
+ else
+ {
+ opt.sweep_interval = val;
+ printf(" sweep interval = %d\n", opt.sweep_interval);
+ }
+ break;
+
+ case 't':
+ opt.transaction_timeout = strtol(optarg, NULL, 0);
+ printf(" Transaction timeout = %d\n", opt.transaction_timeout);
+
+ break;
+
+ case 'n':
+ opt.max_wire_smps = strtol(optarg, NULL, 0);
+ if( opt.max_wire_smps <= 0 )
+ opt.max_wire_smps = 0x7FFFFFFF;
+ printf(" Max wire smp's = %d\n", opt.max_wire_smps);
+ break;
+
+ case 'd':
+ dbg_lvl = strtol(optarg, NULL, 0);
+ printf(" d level = 0x%x\n", dbg_lvl);
+ if (dbg_lvl == 0)
+ {
+ printf(" Debug mode: Ignore Other SMs\n");
+ opt.ignore_other_sm = TRUE;
+ }
+ else if(dbg_lvl == 1)
+ {
+ printf(" Debug mode: Force Signale Thread\n");
+ opt.single_thread = TRUE;
+ }
+ else if(dbg_lvl == 2)
+ {
+ printf(" Debug mode: Force Log Flush\n");
+ opt.force_log_flush = TRUE;
+ }
+ else if(dbg_lvl == 3)
+ {
+ printf(" Debug mode: Disable multicast support\n");
+ opt.disable_multicast = TRUE;
+ }
+ else if(dbg_lvl == 4)
+ {
+ mem_track = TRUE;
+ }
+ else if(dbg_lvl >= 10)
+ {
+ /* Please look at subnet.h for list of testability modes. */
+ opt.testability_mode = dbg_lvl - 9;
+ }
+ else
+ printf( " OpenSM: Unknown debug option %d ignored\n",
+ dbg_lvl );
+ break;
+
+ case 'l':
+ temp = strtol(optarg, NULL, 0);
+ if( temp > 7 )
+ {
+ fprintf(stderr, "ERROR: LMC must be 7 or less.");
+ return( -1 );
+ }
+ opt.lmc = (uint8_t)temp;
+ printf(" LMC = %d\n", temp);
+ break;
+
+ case 'D':
+ log_flags = strtol(optarg, NULL, 0);
+ printf(" verbose option -D = 0x%x\n", log_flags);
+ break;
+
+ case 'f':
+ if (!strcmp(optarg, "stdout"))
+ /* output should be to standard output */
+ opt.log_file = NULL;
+ else
+ opt.log_file = optarg;
+ break;
+
+ case 'v':
+ log_flags = (log_flags <<1 )|1;
+ printf(" Verbose option -v (log flags = 0x%X)\n", log_flags );
+ break;
+
+ case 'V':
+ log_flags = 0xFFFFFFFF;
+ opt.force_log_flush = TRUE;
+ printf(" Big V selected\n");
+ break;
+
+ case 'p':
+ temp = strtol(optarg, NULL, 0);
+ if (0 > temp || 15 < temp) {
+ fprintf(stderr, "ERROR: priority must be between 0 and 15\n");
+ return (-1);
+ }
+ opt.sm_priority = (uint8_t)temp;
+ printf(" Priority = %d\n", temp);
+ break;
+
+ case 'u':
+ opt.updn_activate = TRUE;
+ printf(" Activate UPDN algorithm\n");
+ break;
+
+ case 'a':
+ /*
+ Specifies port guids file
+ */
+ opt.updn_guid_file = optarg;
+ printf (" UPDN Guid File: %s\n", opt.updn_guid_file );
+ break;
+
+ case 'c':
+ cache_options = TRUE;
+ printf (" Caching command line options\n");
+ break;
+
+ case 'h':
+ case '?':
+ case ':':
+ show_usage();
+ break;
+
+ case -1:
+ break; /* done with option */
+ default: /* something wrong */
+ abort();
+ }
+ }
+ while(next_option != -1);
+
+ if (osm_exit_flag) {
+ return( 0 );
+ }
+ if (opt.log_file != NULL )
+ printf(" Log File: %s\n", opt.log_file );
+ /* Done with options description */
+ printf("-------------------------------------------------\n");
+
+ if (mem_track) __cl_mem_track(TRUE);
+
+ opt.log_flags = (uint8_t)log_flags;
+
+ if ( cache_options == TRUE )
+ osm_subn_write_conf_file( &opt );
+
+ status = osm_opensm_init( &osm, &opt );
+ if( status != IB_SUCCESS )
+ {
+ const char *err_str = ib_get_err_str( status );
+ if (err_str == NULL)
+ {
+ err_str = "Unknown Error Type";
+ }
+ printf( "\nError from osm_opensm_init: %s.\n",
+ err_str);
+ /* We will just exit, and not go to Exit, since we don't
+ want the destroy to be called. */
+ return( status );
+ }
+
+ /*
+ If the user didn't specify a GUID on the command line,
+ then get a port GUID value with which to bind.
+ */
+ if( guid == 0 || cl_hton64(guid) == cl_hton64(INVALID_GUID))
+ guid = get_port_guid( &osm, guid );
+
+ if ( guid == 0 )
+ {
+ printf( "Error: Could not get port guid \n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ status = osm_opensm_bind( &osm, guid );
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from osm_opensm_bind (0x%X)\n", status );
+ goto Exit;
+ }
+
+ /*
+ * Define some port guids to ignore during path equalization
+ */
+ if (ignore_guids_file_name != NULL)
+ {
+ status = parse_ignore_guids_file(ignore_guids_file_name, &osm);
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from parse_ignore_guids_file (0x%X)\n", status );
+ goto Exit;
+ }
+ }
+
+ osm_opensm_sweep( &osm );
+ /* since osm_opensm_init get opt as RO we'll set the opt value with UI pfn here */
+ /* Now do the registration */
+ if (opt.updn_activate)
+ if (osm_updn_reg_calc_min_hop_table(osm.p_updn_ucast_routing, &(osm.subn.opt))) {
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( run_once_flag == TRUE )
+ {
+ status = osm_opensm_wait_for_subnet_up(
+ &osm, EVENT_NO_TIMEOUT, TRUE );
+ osm_exit_flag = 1;
+ }
+ else
+ {
+ /*
+ Sit here forever
+ In the future, some sort of console interactivity could
+ be implemented in this loop.
+ */
+ while( !osm_exit_flag )
+ cl_thread_suspend( 10000 );
+ }
+
+ /* wait for all transactions to end */
+ CL_ASSERT( ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0) < 0x100000000ULL );
+ exitTimeout =
+ (uint32_t) ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0);
+
+ if (exitTimeout < 3) exitTimeout = 3;
+
+ /*
+ printf( "\n------- OpenSM Exiting (in %u seconds) -------\n",
+ exitTimeout);
+ sleep(exitTimeout);
+ */
+
+ if ((osm.mad_pool.mads_out))
+ fprintf(stdout,
+ "There are still %u mads out. Forcing the exit of the OpenSM application...\n",
+ osm.mad_pool.mads_out);
+
+ Exit:
+ osm_opensm_destroy( &osm );
+
+ if (mem_track) cl_mem_display();
+
+ exit( 0 );
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+\r
+#include <ics_ver.h>\r
+\r
+#define VER_FILETYPE VFT_APP\r
+#define VER_FILESUBTYPE VFT2_UNKNOWN\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR "Debug OpenSM Subnet Manager Application"\r
+#define VER_INTERNALNAME_STR "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR "opensm.exe"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR "OpenSM Subnet Manager Application"\r
+#define VER_INTERNALNAME_STR "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR "opensm.exe"\r
+#endif\r
+#include <common.ver>\r
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implemntation of the osm_db interface using simple text files
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/st.h>
+#include <opensm/osm_db.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+/****d* Database/OSM_DB_MAX_LINE_LEN
+ * NAME
+ * OSM_DB_MAX_LINE_LEN
+ *
+ * DESCRIPTION
+ * The Maximal line length allowed for the file
+ *
+ * SYNOPSIS
+ */
+#define OSM_DB_MAX_LINE_LEN 1024
+/**********/
+
+/****s* OpenSM: Database/osm_db_domain_imp
+ * NAME
+ * osm_db_domain_imp
+ *
+ * DESCRIPTION
+ * An implementation for domain of the database based on text files and
+ * hash tables.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_db_domain_imp {
+ char *file_name;
+ st_table *p_hash;
+ cl_spinlock_t lock;
+} osm_db_domain_imp_t;
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ * osm_db_domain_t
+ *********/
+
+/****s* OpenSM: Database/osm_db_imp_t
+ * NAME
+ * osm_db_imp_t
+ *
+ * DESCRIPTION
+ * An implementation for file based database
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_db_imp {
+ char *db_dir_name;
+} osm_db_imp_t;
+/*
+ * FIELDS
+ *
+ * db_dir_name
+ * The directory holding the database
+ *
+ * SEE ALSO
+ * osm_db_t
+ *********/
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_construct(
+ IN osm_db_t* const p_db )
+{
+ cl_memclr(p_db, sizeof(osm_db_t));
+ cl_list_construct( &p_db->domains );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_domain_destroy(
+ IN osm_db_domain_t* const p_db_domain)
+{
+ osm_db_domain_imp_t *p_domain_imp;
+ p_domain_imp = (osm_db_domain_imp_t *)p_db_domain->p_domain_imp;
+ osm_db_clear( p_db_domain );
+
+ cl_spinlock_destroy( &p_domain_imp->lock );
+
+ st_free_table( p_domain_imp->p_hash );
+ cl_free( p_domain_imp->file_name );
+ cl_free( p_domain_imp );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_destroy(
+ IN osm_db_t* const p_db )
+{
+ osm_db_domain_t *p_domain;
+
+ while ((p_domain = cl_list_remove_head( &p_db->domains )) != NULL )
+ {
+ osm_db_domain_destroy( p_domain );
+ cl_free( p_domain );
+ }
+ cl_list_destroy( &p_db->domains );
+ cl_free( p_db->p_db_imp );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_init(
+ IN osm_db_t* const p_db,
+ IN osm_log_t *p_log )
+{
+ osm_db_imp_t *p_db_imp;
+ struct stat dstat;
+
+ OSM_LOG_ENTER( p_log, osm_db_init );
+
+ p_db_imp = (osm_db_imp_t *)cl_malloc(sizeof(osm_db_imp_t));
+ CL_ASSERT( p_db_imp != NULL);
+
+ p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR");
+ if ( p_db_imp->db_dir_name == NULL )
+ p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR;
+
+ /* create the directory if it doesn't exist */
+ /* There is difference between creating in windows and in linux */
+#ifdef __WIN__
+ /* Check if the directory exists. If not - create it. */
+ CreateDirectory(p_db_imp->db_dir_name, NULL);
+#else /* __WIN__ */
+ /* make sure the directory exists, also if it is a link */
+ if (lstat(p_db_imp->db_dir_name, &dstat))
+ {
+ if (mkdir(p_db_imp->db_dir_name, 777))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_init: ERR 6901: "
+ " Fail to create the db directory:%s\n",
+ p_db_imp->db_dir_name);
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ }
+#endif
+
+ p_db->p_log = p_log;
+ p_db->p_db_imp = (void*)p_db_imp;
+
+ cl_list_init( &p_db->domains, 5 );
+
+ OSM_LOG_EXIT( p_log );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+osm_db_domain_t*
+osm_db_domain_init(
+ IN osm_db_t* const p_db,
+ IN char *domain_name)
+{
+ osm_db_domain_t *p_domain;
+ osm_db_domain_imp_t *p_domain_imp;
+ int dir_name_len;
+ osm_log_t *p_log = p_db->p_log;
+ FILE *p_file;
+
+ OSM_LOG_ENTER( p_log, osm_db_domain_init );
+
+ /* allocate a new domain object */
+ p_domain = (osm_db_domain_t *)cl_malloc(sizeof(osm_db_domain_t));
+ CL_ASSERT( p_domain != NULL );
+
+ p_domain_imp =
+ (osm_db_domain_imp_t *)cl_malloc(sizeof(osm_db_domain_imp_t));
+ CL_ASSERT( p_domain_imp != NULL );
+
+ dir_name_len = strlen(((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+
+ /* set the domain file name */
+ p_domain_imp->file_name =
+ (char *)cl_malloc(sizeof(char)*(dir_name_len) + strlen(domain_name) + 2);
+ CL_ASSERT(p_domain_imp->file_name != NULL);
+ strcpy(p_domain_imp->file_name,((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+ strcat(p_domain_imp->file_name,domain_name);
+
+ /* make sure the file exists - or exit if not writable */
+ p_file = fopen(p_domain_imp->file_name, "a+");
+ if (! p_file)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_domain_init: ERR 6902: "
+ " Fail to open the db file:%s\n",
+ p_domain_imp->file_name);
+ cl_free(p_domain_imp);
+ cl_free(p_domain);
+ p_domain = NULL;
+ goto Exit;
+ }
+ fclose(p_file);
+
+ /* initialize the hash table object */
+ p_domain_imp->p_hash = st_init_strtable();
+ CL_ASSERT( p_domain_imp->p_hash != NULL );
+
+ p_domain->p_db = p_db;
+ cl_list_insert_tail( &p_db->domains, p_domain );
+ p_domain->p_domain_imp = p_domain_imp;
+ cl_spinlock_construct( &p_domain_imp->lock );
+ cl_spinlock_init( &p_domain_imp->lock );
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return p_domain;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_restore(
+ IN osm_db_domain_t *p_domain)
+{
+
+ osm_log_t *p_log = p_domain->p_db->p_log;
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ FILE *p_file;
+ int status;
+ char sLine[OSM_DB_MAX_LINE_LEN];
+ boolean_t before_key;
+ char *p_first_word, *p_rest_of_line, *p_last;
+ char *p_key = NULL;
+ char *p_prev_val, *p_accum_val = NULL;
+ unsigned int line_num;
+
+ OSM_LOG_ENTER( p_log, osm_db_restore );
+
+ /* take the lock on the domain */
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ /* open the file - read mode */
+ p_file = fopen(p_domain_imp->file_name, "r");
+
+ if (! p_file)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: ERR 6903: "
+ " Fail to open the db file:%s\n",
+ p_domain_imp->file_name);
+ status = 1;
+ goto Exit;
+ }
+
+ /* parse the file allocating new hash tables as required */
+ /*
+ states:
+ before_key (0) -> in_key (1)
+
+ before_key: if a word on the first byte - it is the key. state=in_key
+ the rest of the line is start of the value.
+ in_key: unless the line is empty - add it (with newlines) to the value.
+ if empty: state=before_key
+ */
+ status = 0;
+ before_key = TRUE;
+ line_num = 0;
+ /* if we got to EOF in the middle of a key we add a last newline */
+ while (
+ (fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) ||
+ ((before_key == FALSE) && strcpy(sLine,"\n"))
+ )
+ {
+ line_num++;
+ if (before_key)
+ {
+ if ((sLine[0] != ' ') && (sLine[0] != '\t') && (sLine[0] != '\n'))
+ {
+ /* we got a new key */
+ before_key = FALSE;
+
+ /* handle the key */
+ p_first_word = strtok_r(sLine, " \t\n", &p_last);
+ if (! p_first_word)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: ERR 6904: "
+ " Fail to get key from line:%u : %s\n",
+ line_num, sLine);
+ status = 1;
+ goto EndParsing;
+ }
+
+ p_key = (char *)cl_malloc(sizeof(char)*(strlen(p_first_word) + 1));
+ strcpy(p_key, p_first_word);
+
+ p_rest_of_line = strtok_r(NULL, "\n", &p_last);
+ if (p_rest_of_line != NULL)
+ {
+ p_accum_val =
+ (char*)cl_malloc(sizeof(char)*(strlen(p_rest_of_line) + 1));
+ strcpy(p_accum_val, p_rest_of_line);
+ }
+ else
+ {
+ p_accum_val = (char*)cl_malloc(2);
+ strcpy(p_accum_val, "\0");
+ }
+ }
+ else if (sLine[0] != '\n')
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: ERR 6905: "
+ " How did we get here? line:%u : %s\n",
+ line_num, sLine);
+ status = 1;
+ goto EndParsing;
+ }
+ } /* before key */
+ else
+ {
+ /* we already have a key */
+
+ if (sLine[0] == '\n')
+ {
+ /* got an end of key */
+ before_key = TRUE;
+
+ /* make sure the key was not previously used */
+ if (st_lookup(p_domain_imp->p_hash,
+ (st_data_t)p_key,
+ (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: ERR 6906: "
+ " Key:%s already exists in:%s with value:%s."
+ " Removing it.\n",
+ p_key,
+ p_domain_imp->file_name,
+ p_prev_val);
+ }
+ else
+ {
+ p_prev_val = NULL;
+ }
+
+ /* store our key and value */
+ st_insert(p_domain_imp->p_hash,
+ (st_data_t)p_key, (st_data_t)p_accum_val);
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_restore: "
+ "Got key:%s value:%s\n", p_key, p_accum_val);
+ }
+ else
+ {
+ /* accumulate into the value */
+ p_prev_val = p_accum_val;
+ p_accum_val =
+ (char *)cl_malloc(strlen(p_prev_val) + strlen(sLine) + 1);
+ strcpy(p_accum_val, p_prev_val);
+ cl_free(p_prev_val);
+ strcat(p_accum_val, sLine);
+ }
+ } /* in key */
+ } /* while lines or last line */
+
+ EndParsing:
+ fclose(p_file);
+
+ Exit:
+ cl_spinlock_release( &p_domain_imp->lock );
+ return status;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+ FILE *p_file = (FILE*)arg;
+ char *p_key = (char*)key;
+ char *p_val = (char *)val;
+
+ fprintf(p_file, "%s %s\n\n", p_key, p_val);
+ return ST_CONTINUE;
+}
+
+int
+osm_db_store(
+ IN osm_db_domain_t *p_domain)
+{
+ osm_log_t *p_log = p_domain->p_db->p_log;
+ osm_db_domain_imp_t *p_domain_imp;
+ FILE *p_file;
+ int status = 0;
+ char *p_tmp_file_name;
+
+ OSM_LOG_ENTER( p_log, osm_db_store );
+
+ p_domain_imp = (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ p_tmp_file_name =
+ (char *)cl_malloc(sizeof(char)*(strlen(p_domain_imp->file_name)+8));
+ strcpy(p_tmp_file_name, p_domain_imp->file_name);
+ strcat(p_tmp_file_name,".tmp");
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ /* open up the output file */
+ p_file = fopen(p_tmp_file_name, "w");
+
+ if (! p_file)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6907: "
+ " Fail to open the db file:%s for writing\n",
+ p_domain_imp->file_name);
+ status = 1;
+ goto Exit;
+ }
+
+ st_foreach(p_domain_imp->p_hash, __osm_dump_tbl_entry, (st_data_t)p_file);
+ fclose(p_file);
+
+ /* move the domain file */
+ status = remove(p_domain_imp->file_name);
+ if (status)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6909: "
+ " Fail to remove file:%s (err:%u)\n",
+ p_domain_imp->file_name, status);
+ }
+ status = rename(p_tmp_file_name, p_domain_imp->file_name);
+ if (status)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6908: "
+ " Fail to rename the db file to:%s (err:%u)\n",
+ p_domain_imp->file_name, status);
+ }
+ Exit:
+ cl_spinlock_release( &p_domain_imp->lock );
+ cl_free(p_tmp_file_name);
+ OSM_LOG_EXIT( p_log );
+ return status;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+/* simply de-allocate the key and the value and return the code
+ that makes the st_foreach delete the entry */
+int
+__osm_clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+ cl_free((char*)key);
+ cl_free((char*)val);
+ return ST_DELETE;
+}
+
+int
+osm_db_clear(
+ IN osm_db_domain_t *p_domain)
+{
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+ st_foreach(p_domain_imp->p_hash, __osm_clear_tbl_entry, (st_data_t)NULL);
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_get_key_of_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+ cl_list_t *p_list = (cl_list_t *)arg;
+ cl_list_insert_tail(p_list, (void*)key);
+ return ST_CONTINUE;
+}
+
+int
+osm_db_keys(
+ IN osm_db_domain_t *p_domain,
+ OUT cl_list_t* p_key_list)
+{
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ st_foreach(p_domain_imp->p_hash,
+ __osm_get_key_of_tbl_entry, (st_data_t)p_key_list);
+
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+char *
+osm_db_lookup(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key)
+{
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ char *p_val = NULL;
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ if (!st_lookup(p_domain_imp->p_hash, (st_data_t)p_key, (st_data_t*)&p_val))
+ p_val = NULL;
+
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return p_val;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_update(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key,
+ IN char *const p_val)
+{
+ osm_log_t *p_log = p_domain->p_db->p_log;
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ char *p_prev_val = NULL;
+ char *p_new_key;
+ char *p_new_val;
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ if (st_lookup(p_domain_imp->p_hash,
+ (st_data_t)p_key, (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_update: "
+ " Key:%s previously exists in:%s with value:%s.\n",
+ p_key,
+ p_domain_imp->file_name,
+ p_prev_val);
+ p_new_key = p_key;
+ }
+ else
+ {
+ /* need to allocate the key */
+ p_new_key = cl_malloc(sizeof(char)*(strlen(p_key) + 1));
+ strcpy(p_new_key, p_key);
+ }
+
+ /* need to arange a new copy of the value */
+ p_new_val = cl_malloc(sizeof(char)*(strlen(p_val) + 1));
+ strcpy(p_new_val, p_val);
+
+ st_insert(p_domain_imp->p_hash, (st_data_t)p_new_key, (st_data_t)p_new_val);
+
+ if (p_prev_val) cl_free(p_prev_val);
+
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_delete(
+ IN osm_db_domain_t *p_domain,
+ IN char *const p_key)
+{
+ osm_log_t *p_log = p_domain->p_db->p_log;
+ osm_db_domain_imp_t *p_domain_imp =
+ (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ char *p_prev_val = NULL;
+ int res;
+
+ OSM_LOG_ENTER( p_log, osm_db_delete );
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+ if (st_delete(p_domain_imp->p_hash,
+ (st_data_t*)&p_key, (st_data_t*)&p_prev_val))
+ {
+ if (st_lookup(p_domain_imp->p_hash,
+ (st_data_t)p_key, (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_delete: "
+ " key:%s still exists in:%s with value:%s.\n",
+ p_key,
+ p_domain_imp->file_name,
+ p_prev_val);
+ res = 1;
+ }
+ else
+ {
+ cl_free(p_key);
+ cl_free(p_prev_val);
+ res = 0;
+ }
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_update: "
+ " fail to find key:%s. delete failed\n",
+ p_key);
+ res = 1;
+ }
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ OSM_LOG_EXIT( p_log );
+ return res;
+}
+
+#ifdef TEST_OSMDB
+#include <stdlib.h>
+#include <math.h>
+
+int
+main(int argc, char **argv)
+{
+ osm_db_t db;
+ osm_log_t log;
+ osm_db_domain_t *p_dbd;
+ cl_list_t keys;
+ cl_list_iterator_t kI;
+ char *p_key;
+ char *p_val;
+ int i;
+
+ cl_list_construct( &keys );
+ cl_list_init( &keys, 10 );
+
+ osm_log_init( &log, TRUE, 0xff, "/tmp/test_osm_db.log");
+
+ osm_db_construct(&db);
+ if (osm_db_init(&db, &log))
+ {
+ printf("db init failed\n");
+ exit(1);
+ }
+
+ p_dbd = osm_db_domain_init(&db, "lid_by_guid");
+
+ if (osm_db_restore(p_dbd))
+ {
+ printf("failed to restore\n");
+ }
+
+ if (osm_db_keys(p_dbd, &keys))
+ {
+ printf("failed to get keys\n");
+ }
+ else
+ {
+ kI = cl_list_head( &keys );
+ while (kI != cl_list_end( & keys ))
+ {
+ p_key = cl_list_obj(kI);
+ kI = cl_list_next( kI );
+
+ p_val = osm_db_lookup(p_dbd, p_key);
+ printf("key = %s val = %s\n", p_key, p_val);
+ }
+ }
+
+ cl_list_remove_all(&keys);
+
+ /* randomly add and remove numbers */
+ for (i = 0; i < 10; i++)
+ {
+ int k;
+ float v;
+ int is_add;
+ char val_buf[16];
+ char key_buf[16];
+
+ k = floor(1.0 * rand()/ RAND_MAX * 100);
+ v = rand();
+ sprintf(key_buf, "%u", k);
+ sprintf(val_buf, "%u", v);
+
+ is_add = (rand() < RAND_MAX/ 2);
+
+ if (is_add)
+ {
+ osm_db_update(p_dbd, key_buf, val_buf);
+ }
+ else
+ {
+ osm_db_delete(p_dbd, key_buf);
+ }
+ }
+ if (osm_db_keys(p_dbd, &keys))
+ {
+ printf("failed to get keys\n");
+ }
+ else
+ {
+ kI = cl_list_head( &keys );
+ while (kI != cl_list_end( & keys ))
+ {
+ p_key = cl_list_obj(kI);
+ kI = cl_list_next( kI );
+
+ p_val = osm_db_lookup(p_dbd, p_key);
+ printf("key = %s val = %s\n", p_key, p_val);
+ }
+ }
+ if (osm_db_store(p_dbd))
+ printf("failed to store\n");
+
+ osm_db_destroy( &db );
+ cl_list_destroy( &keys );
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <opensm/osm_db_pack.h>
+static inline void
+__osm_pack_guid(uint64_t guid, char *p_guid_str)
+{
+ sprintf(p_guid_str, "0x%016" PRIx64, guid);
+}
+
+static inline uint64_t
+__osm_unpack_guid(char *p_guid_str)
+{
+#if __WORDSIZE == 64
+ return (strtoul(p_guid_str, NULL, 0));
+#else
+ return (strtoull(p_guid_str, NULL, 0));
+#endif
+}
+
+static inline void
+__osm_pack_lids(uint16_t min_lid, uint16_t max_lid, char *p_lid_str)
+{
+ sprintf(p_lid_str, "0x%04x 0x%04x", min_lid, max_lid);
+}
+
+static inline int
+__osm_unpack_lids(
+ IN char *p_lid_str,
+ OUT uint16_t *p_min_lid,
+ OUT uint16_t *p_max_lid )
+{
+ unsigned long tmp;
+ char *p_next;
+ char *p_num;
+ char lids_str[24];
+
+ strncpy(lids_str, p_lid_str, 23);
+ lids_str[23] = '\0';
+ p_num = strtok_r(lids_str, " \t", &p_next);
+ if (! p_num) return 1;
+ tmp = strtoul(p_num, NULL, 0);
+ CL_ASSERT( tmp < 0x10000 );
+ *p_min_lid = (uint16_t)tmp;
+
+ p_num = strtok_r(NULL, " \t", &p_next);
+ if (! p_num) return 1;
+ tmp = strtoul(p_num, NULL, 0);
+ CL_ASSERT( tmp < 0x10000 );
+ *p_max_lid = (uint16_t)tmp;
+
+ return 0;
+}
+
+int
+osm_db_guid2lid_guids(
+ IN osm_db_domain_t* const p_g2l,
+ OUT cl_qlist_t* p_guid_list )
+{
+ char *p_key;
+ cl_list_t keys;
+ osm_db_guid_elem_t *p_guid_elem;
+
+ cl_list_construct( &keys );
+ cl_list_init( &keys , 10);
+
+ if (osm_db_keys(p_g2l, &keys))
+ return 1;
+
+ while ( (p_key = cl_list_remove_head( &keys )) != NULL )
+ {
+ p_guid_elem = (osm_db_guid_elem_t*)cl_malloc(sizeof(osm_db_guid_elem_t));
+ CL_ASSERT( p_guid_elem != NULL );
+
+ p_guid_elem->guid = __osm_unpack_guid(p_key);
+ cl_qlist_insert_head(p_guid_list, &p_guid_elem->item);
+ }
+
+ cl_list_destroy( &keys );
+ return 0;
+}
+
+int
+osm_db_guid2lid_get(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid,
+ OUT uint16_t *p_min_lid,
+ OUT uint16_t *p_max_lid)
+{
+ char guid_str[20];
+ char *p_lid_str;
+ uint16_t min_lid, max_lid;
+
+ __osm_pack_guid(guid, guid_str);
+ p_lid_str = osm_db_lookup(p_g2l, guid_str);
+ if (! p_lid_str)
+ return 1;
+ if (__osm_unpack_lids(p_lid_str, &min_lid, &max_lid))
+ return 1;
+
+ if (p_min_lid) *p_min_lid = min_lid;
+ if (p_max_lid) *p_max_lid = max_lid;
+
+ return 0;
+}
+
+int
+osm_db_guid2lid_set(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid,
+ IN uint16_t min_lid,
+ IN uint16_t max_lid)
+{
+ char guid_str[20];
+ char lid_str[16];
+
+ __osm_pack_guid(guid, guid_str);
+ __osm_pack_lids(min_lid, max_lid, lid_str);
+
+ return( osm_db_update( p_g2l, guid_str, lid_str) );
+}
+
+int
+osm_db_guid2lid_delete(
+ IN osm_db_domain_t* const p_g2l,
+ IN uint64_t guid )
+{
+ char guid_str[20];
+ __osm_pack_guid(guid, guid_str);
+ return( osm_db_delete( p_g2l, guid_str) );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_ptr_vector.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_construct(
+ IN osm_drop_mgr_t* const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_destroy(
+ IN osm_drop_mgr_t* const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_destroy );
+
+ CL_ASSERT( p_mgr );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_drop_mgr_init(
+ IN osm_drop_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_drop_mgr_init );
+
+ osm_drop_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_remove_port(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_port_t* p_port )
+{
+ ib_net64_t port_guid;
+ osm_port_t *p_port_check;
+ cl_list_t* p_new_ports_list;
+ cl_list_iterator_t cl_list_item;
+ cl_qmap_t* p_port_guid_tbl;
+ cl_qmap_t* p_sm_guid_tbl;
+ osm_mcm_info_t* p_mcm;
+ osm_mgrp_t* p_mgrp;
+ cl_ptr_vector_t* p_port_lid_tbl;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint32_t port_num;
+ uint32_t remote_port_num;
+ uint32_t num_physp;
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+ osm_remote_sm_t *p_sm;
+ ib_gid_t port_gid;
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+ char* p_node_desc;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_port );
+
+ port_guid = osm_port_get_guid( p_port );
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Unreachable port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+
+ /*
+ Remove this port from the new_ports_list, if it exists there.
+ Remove this port from the guid and LID tables.
+ Remove also from the sm guid table - if the object
+ exists there.
+ */
+ p_new_ports_list = &p_mgr->p_subn->new_ports_list;
+ cl_list_item = cl_list_head(p_new_ports_list);
+ while( cl_list_item != cl_list_end(p_new_ports_list) )
+ {
+ if ( (osm_port_t*)(cl_list_obj(cl_list_item)) == p_port )
+ {
+ /* Found the port in the new_ports_list. Remove it from there. */
+ cl_list_remove_item(p_new_ports_list, cl_list_item);
+ break;
+ }
+ cl_list_item = cl_list_next(cl_list_item);
+ }
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl;
+ p_sm_guid_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+ p_port_check = (osm_port_t*)cl_qmap_remove( p_port_guid_tbl, port_guid );
+ if( p_port_check != p_port )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_port: ERR 0101: "
+ "Port 0x%016" PRIx64 " not in guid table.\n",
+ cl_ntoh64( port_guid ) );
+ goto Exit;
+ }
+
+ p_sm = (osm_remote_sm_t*)cl_qmap_remove(p_sm_guid_tbl, port_guid );
+ if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_guid_tbl ) )
+ {
+ /* need to remove this item */
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Cleaned sm for port guid\n" );
+
+ cl_free(p_sm);
+ }
+
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Clearing abandoned LID range [0x%X,0x%X].\n",
+ min_lid_ho, max_lid_ho );
+
+ for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ cl_ptr_vector_set( p_port_lid_tbl, lid_ho, NULL );
+
+ /*
+ For each Physical Port associated with this port:
+ Unlink the remote Physical Port, if any
+ Re-initialize each Physical Port.
+ */
+
+ num_physp = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_physp; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)port_num );
+
+ if( p_physp )
+ {
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ osm_port_t* p_remote_port;
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+ p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+ remote_port_num = osm_physp_get_port_num( p_remote_physp );
+ p_remote_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, p_remote_physp->port_guid );
+
+ if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ /* Let's check if this is a case of link that is lost (both ports
+ weren't recognized), or a "hiccup" in the subnet - in which case
+ the remote port was recognized, and its state is ACTIVE.
+ If this is just a "hiccup" - force a heavy sweep in the next sweep. We don't
+ want to loose that part of the subnet. */
+ if (osm_port_discovery_count_get( p_remote_port ) &&
+ osm_physp_get_port_state( p_remote_physp ) == IB_LINK_ACTIVE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Forcing delayed heavy sweep. Remote "
+ "port 0x%016" PRIx64 " port num: 0x%X "
+ "was recognized in ACTIVE state \n",
+ cl_ntoh64( p_remote_physp->port_guid ),
+ remote_port_num );
+ p_mgr->p_subn->force_delayed_heavy_sweep = TRUE;
+ }
+ }
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Unlinking local node 0x%016" PRIx64 ", port 0x%X"
+ "\n\t\t\t\tand remote node 0x%016" PRIx64
+ ", port 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ remote_port_num );
+
+ osm_node_unlink( p_node, (uint8_t)port_num,
+ p_remote_node, (uint8_t)remote_port_num );
+
+ /* If ther remote node is a ca - need to remove the remote port, since
+ it is no longer reachable. This can be done if we reset the discovery
+ count of the remote port. */
+ if ( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_CA )
+ {
+ if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ osm_port_discovery_count_reset( p_remote_port );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_drop_mgr_remove_port: "
+ "resetting discovery count of node: "
+ "0x%016" PRIx64 " port num:%u.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ remote_port_num );
+ }
+ }
+ }
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_drop_mgr_remove_port: "
+ "Clearing physical port number %u.\n",
+ port_num );
+
+ osm_physp_destroy( p_physp );
+ }
+ }
+
+ p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+ while( p_mcm != (osm_mcm_info_t *)cl_qlist_end( &p_port->mcm_list ) )
+ {
+ p_mgrp = (osm_mgrp_t *)cl_qmap_get( &p_mgr->p_subn->mgrp_mlid_tbl,
+ p_mcm->mlid );
+ if(p_mgrp != (osm_mgrp_t *)cl_qmap_end( &p_mgr->p_subn->mgrp_mlid_tbl ) )
+ {
+ osm_mgrp_remove_port(p_mgr->p_subn, p_mgr->p_log, p_mgrp, p_port->guid );
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ }
+ p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+ }
+
+ /* initialize the p_node_desc */
+ p_node_desc = p_port->p_node ? (char*)(p_port->p_node->node_desc.description) : "UNKNOWN";
+ osm_port_delete( &p_port );
+
+
+ /* issue a notice - trap 65 */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type(¬ice, CL_HTON32(4)); /* A class manager generator */
+ /* endport ceases to be reachable */
+ notice.g_or_v.generic.trap_num = CL_HTON16(65);
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+ /* following C14-72.1.2 and table 119 p725 */
+ /* we need to provide the GID */
+ port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+ port_gid.unicast.interface_id = port_guid;
+ cl_memcpy(&(notice.data_details.ntc_64_67.gid),
+ &(port_gid),
+ sizeof(ib_gid_t));
+
+ /* According to page 653 - the issuer gid in this case of trap
+ is the SM gid, since the SM is the initiator of this trap. */
+ notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_mgr->p_log, p_mgr->p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_port: ERR 0103: "
+ "Error sending trap reports (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ osm_log( p_mgr->p_log, OSM_LOG_INFO,
+ "Removed port with GUID:0x%016" PRIx64
+ " LID range [0x%X,0x%X] of node:%s \n",
+ cl_ntoh64( port_gid.unicast.interface_id ),
+ min_lid_ho, max_lid_ho, p_node_desc );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_remove_switch(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ osm_switch_t *p_sw;
+ cl_qmap_t* p_sw_guid_tbl;
+ ib_net64_t node_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_switch );
+
+ node_guid = osm_node_get_node_guid( p_node );
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ p_sw = (osm_switch_t*)cl_qmap_remove( p_sw_guid_tbl, node_guid );
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_switch: ERR 0102: "
+ "Node 0x%016" PRIx64 " not in switch table.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+ else
+ {
+ osm_switch_delete( &p_sw );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_remove_router(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_router );
+
+ UNUSED_PARAM( p_mgr );
+ UNUSED_PARAM( p_node );
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_router: ERR 0106: "
+ "Routers are not supported.\n" );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+__osm_drop_mgr_process_node(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ osm_physp_t *p_physp;
+ osm_port_t *p_port;
+ osm_node_t *p_node_check;
+ cl_qmap_t *p_node_guid_tbl;
+ uint32_t port_num;
+ uint32_t max_ports;
+ ib_net64_t port_guid;
+ cl_qmap_t* p_port_guid_tbl;
+ boolean_t return_val = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_process_node );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_process_node: "
+ "Unreachable node 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+
+ /*
+ Delete all the logical and physical port objects
+ associated with this node.
+ */
+ p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ max_ports = osm_node_get_num_physp( p_node );
+ for( port_num = 0; port_num < max_ports; port_num++ )
+ {
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ if( osm_physp_is_valid( p_physp ) )
+ {
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ p_port = (osm_port_t*)cl_qmap_get(
+ p_port_guid_tbl, port_guid );
+
+ if( p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ __osm_drop_mgr_remove_port( p_mgr, p_port );
+ }
+ }
+
+ return_val = TRUE;
+
+ switch( osm_node_get_type( p_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ break;
+
+ case IB_NODE_TYPE_SWITCH:
+ __osm_drop_mgr_remove_switch( p_mgr, p_node );
+ break;
+
+ case IB_NODE_TYPE_ROUTER:
+ __osm_drop_mgr_remove_router( p_mgr, p_node );
+ break;
+
+ default:
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_process_node: ERR 0104: "
+ "Node 0x%016" PRIx64 " unknown node type: %u.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_node_get_type( p_node ) );
+ break;
+ }
+
+ p_node_check = (osm_node_t*)cl_qmap_remove( p_node_guid_tbl,
+ osm_node_get_node_guid( p_node ) );
+ if( p_node_check != p_node )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_process_node: ERR 0105: "
+ "Node 0x%016" PRIx64 " not in guid table.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ /* free memory allocated to node */
+ osm_node_delete( &p_node );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( return_val );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_check_node(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ osm_switch_t *p_sw;
+ cl_qmap_t* p_sw_guid_tbl;
+ ib_net64_t node_guid;
+ osm_physp_t *p_physp;
+ osm_port_t *p_port;
+ cl_qmap_t* p_port_guid_tbl;
+ ib_net64_t port_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_check_node );
+
+ node_guid = osm_node_get_node_guid( p_node );
+
+ if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: ERR 0107: "
+ "Node 0x%016" PRIx64 " is not a switch node\n",
+ cl_ntoh64( node_guid ) );
+ goto Exit;
+ }
+
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ /* Make sure we have a switch object for this node */
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl, node_guid );
+ if (p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+ {
+ /* We do not have switch info for this node */
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " no switch in table.\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ /* Make sure we have a port object for port zero */
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_physp = osm_node_get_physp_ptr( p_node, 0 );
+ if ( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " no valid physical port 0.\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ p_port = (osm_port_t*)cl_qmap_get(
+ p_port_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " no port object.\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ if ( osm_port_discovery_count_get( p_port ) == 0 )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " port has discovery count zero.\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_process(
+ IN const osm_drop_mgr_t* const p_mgr )
+{
+ cl_qmap_t *p_node_guid_tbl;
+ cl_qmap_t *p_port_guid_tbl;
+ cl_list_t *p_lsweep_ports;
+ osm_port_t *p_port;
+ osm_port_t *p_next_port;
+ osm_node_t *p_node;
+ osm_node_t *p_next_node;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_process );
+
+ CL_ASSERT( p_mgr );
+
+ p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_lsweep_ports = &p_mgr->p_subn->light_sweep_physp_list;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );
+ while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+ {
+ p_node = p_next_node;
+ p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+
+ CL_ASSERT( cl_qmap_key( &p_node->map_item ) ==
+ osm_node_get_node_guid( p_node ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ node_guid = osm_node_get_node_guid( p_node );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking node 0x%016" PRIx64 ".\n",
+ cl_ntoh64( node_guid ) );
+ }
+
+ /*
+ Check if this node was discovered during the last sweep.
+ If not, it is unreachable in the current subnet, and
+ should therefore be removed from the subnet object.
+ */
+ if( osm_node_discovery_count_get( p_node ) == 0 )
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ }
+
+ /*
+ Go over all the nodes. If the node is a switch - make sure
+ there is also a switch record for it, and portInfo record for
+ port zero of of the node.
+ If not - this means that there was some error in getting the data
+ of this node. Drop the node.
+ */
+ p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );
+ while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+ {
+ p_node = p_next_node;
+ p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ node_guid = osm_node_get_node_guid( p_node );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking full discovery of node 0x%016" PRIx64 ".\n",
+ cl_ntoh64( node_guid ) );
+ }
+
+ if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+ continue;
+
+ /* We are handling a switch node */
+ __osm_drop_mgr_check_node( p_mgr, p_node );
+ }
+
+ p_next_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+ while( p_next_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ p_port = p_next_port;
+ p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item );
+
+ CL_ASSERT( cl_qmap_key( &p_port->map_item ) ==
+ osm_port_get_guid( p_port ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ port_guid = osm_port_get_guid( p_port );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ }
+
+ /*
+ If the port is unreachable, remove it from the guid table.
+ */
+ if( osm_port_discovery_count_get( p_port ) == 0 )
+ __osm_drop_mgr_remove_port( p_mgr, p_port );
+ }
+
+ /*
+ scan through all the ports left - if the port is not DOWN and
+ it does not have a valid remote port - we need to track it for
+ next light sweep scan...
+ */
+ cl_list_remove_all( p_lsweep_ports );
+ p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );
+ while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+ {
+ p_node = p_next_node;
+ p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+
+ for (port_num = 1; port_num < osm_node_get_num_physp(p_node); port_num++)
+ {
+ p_physp = osm_node_get_physp_ptr(p_node, port_num);
+ if (osm_physp_is_valid(p_physp) &&
+ (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) &&
+ ! osm_physp_get_remote(p_physp))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_drop_mgr_process: ERR 0108: "
+ "Unknown remote side for node 0x%016" PRIx64
+ " port %u. Adding to light sweep sampling list.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node )),
+ port_num);
+
+ osm_dump_dr_path(p_mgr->p_log,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ OSM_LOG_ERROR);
+
+ cl_list_insert_head( p_lsweep_ports, p_physp );
+ }
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_fwd_tbl_t.
+ * This object represents a unicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_fwd_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_fwd_tbl_init(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const ib_switch_info_t* const p_si )
+{
+ uint16_t tbl_cap;
+ ib_api_status_t status = IB_SUCCESS;
+ /*
+ Determine the type and size of the forwarding table
+ used by this switch, then initialize accordingly.
+ The current implementation only supports switches
+ with linear forwarding tables.
+ */
+ tbl_cap = cl_ntoh16( p_si->lin_cap );
+
+ if( tbl_cap == 0 )
+ {
+ /*
+ This switch does not support linear forwarding
+ tables. Error out for now.
+ */
+ status = IB_UNSUPPORTED;
+ goto Exit;
+ }
+
+ p_tbl->p_rnd_tbl = NULL;
+
+ p_tbl->p_lin_tbl = osm_lin_tbl_new( tbl_cap );
+
+ if( p_tbl->p_lin_tbl == NULL )
+ {
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ Exit:
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_fwd_tbl_destroy(
+ IN osm_fwd_tbl_t* const p_tbl )
+{
+ if( p_tbl->p_lin_tbl )
+ {
+ CL_ASSERT( p_tbl->p_rnd_tbl == NULL );
+ osm_lin_tbl_delete( &p_tbl->p_lin_tbl );
+ }
+ else
+ {
+ osm_rand_tbl_delete( &p_tbl->p_rnd_tbl );
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of inform record functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.18 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_trap_rcv.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+
+typedef struct _osm_infr_match_ctxt
+{
+ cl_list_t *p_remove_infr_list;
+ ib_mad_notice_attr_t *p_ntc;
+
+} osm_infr_match_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_infr_construct(
+ IN osm_infr_t* const p_infr )
+{
+ cl_memclr( p_infr, sizeof(osm_infr_t) );
+}
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_infr_destroy(
+ IN osm_infr_t* const p_infr )
+{
+ cl_free(p_infr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_init(
+ IN osm_infr_t* const p_infr,
+ IN const osm_infr_t *p_infr_rec )
+{
+ CL_ASSERT( p_infr );
+
+ /* what else do we need in the inform_record ??? */
+
+ /* copy the contents of the provided informinfo */
+ cl_memcpy(p_infr,p_infr_rec, sizeof(osm_infr_t));
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+osm_infr_t*
+osm_infr_new(
+ IN const osm_infr_t *p_infr_rec )
+{
+ osm_infr_t* p_infr;
+
+ CL_ASSERT(p_infr_rec);
+
+ p_infr = (osm_infr_t*)cl_malloc( sizeof(osm_infr_t) );
+ if( p_infr )
+ {
+ osm_infr_construct( p_infr );
+ osm_infr_init( p_infr, p_infr_rec );
+ }
+
+ return( p_infr );
+}
+
+/**********************************************************************
+ * Match an infr by the RID of the stored inform_info_record
+ **********************************************************************/
+static
+cl_status_t
+__match_rid_of_inf_rec(
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ ib_inform_info_record_t* p_infr_rec = (ib_inform_info_record_t *)context;
+ osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+ int32_t count;
+
+
+ count = cl_memcmp(
+ &p_infr->inform_record,
+ p_infr_rec,
+ sizeof(p_infr_rec->subscriber_gid) +
+ sizeof(p_infr_rec->subscriber_enum) );
+
+ if(count == 0)
+ return CL_SUCCESS;
+ else
+ return CL_NOT_FOUND;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+osm_infr_t*
+osm_infr_get_by_rid(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN ib_inform_info_record_t* const p_infr_rec )
+{
+ cl_list_item_t* p_list_item;
+ OSM_LOG_ENTER( p_log, osm_infr_get_by_rid );
+
+ p_list_item = cl_qlist_find_from_head(
+ &p_subn->sa_infr_list,
+ __match_rid_of_inf_rec,
+ p_infr_rec);
+
+ if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) )
+ p_list_item = NULL;
+
+ OSM_LOG_EXIT( p_log );
+ return (osm_infr_t*)p_list_item;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__dump_all_informs(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log)
+{
+ cl_list_item_t* p_list_item;
+ OSM_LOG_ENTER( p_log, __dump_all_informs );
+
+ p_list_item = cl_qlist_head( &p_subn->sa_infr_list );
+ while (p_list_item != cl_qlist_end( &p_subn->sa_infr_list ))
+ {
+ osm_dump_inform_info(p_log,
+ &((osm_infr_t*)p_list_item)->inform_record.inform_info,
+ OSM_LOG_DEBUG);
+ p_list_item = cl_qlist_next( p_list_item );
+ }
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Match an infr by the InformInfo and Address vector
+ **********************************************************************/
+static
+cl_status_t
+__match_inf_rec(
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ osm_infr_t* p_infr_rec = (osm_infr_t *)context;
+ osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+ osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log;
+ cl_status_t status;
+ int32_t count1, count2;
+
+ OSM_LOG_ENTER( p_log, __match_inf_rec);
+ count1 = cl_memcmp(&p_infr->report_addr, &p_infr_rec->report_addr,
+ sizeof(p_infr_rec->report_addr));
+ if (count1)
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec : "
+ "Differ by Address\n");
+ count2 = cl_memcmp(
+ &p_infr->inform_record.inform_info,
+ &p_infr_rec->inform_record.inform_info,
+ sizeof(p_infr->inform_record.inform_info));
+ if (count2)
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec : "
+ "Differ by InformInfo\n" );
+ if ((count1 == 0) && (count2 == 0))
+ status = CL_SUCCESS;
+ else
+ status = CL_NOT_FOUND;
+
+ OSM_LOG_EXIT( p_log );
+ return status;
+
+}
+/**********************************************************************
+ **********************************************************************/
+
+osm_infr_t*
+osm_infr_get_by_rec(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t* const p_infr_rec )
+{
+ cl_list_item_t* p_list_item;
+
+ OSM_LOG_ENTER( p_log, osm_infr_get_by_rec );
+
+ __dump_all_informs(p_subn, p_log);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_get_by_rec: "
+ "Looking for Inform Record:\n");
+ osm_dump_inform_info(p_log, &(p_infr_rec->inform_record.inform_info),
+ OSM_LOG_DEBUG);
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_get_by_rec: "
+ "InformInfo list size is : %d\n",
+ cl_qlist_count(&p_subn->sa_infr_list) );
+ p_list_item = cl_qlist_find_from_head(
+ &p_subn->sa_infr_list,
+ __match_inf_rec,
+ p_infr_rec);
+
+ if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) )
+ p_list_item = NULL;
+ OSM_LOG_EXIT( p_log );
+ return (osm_infr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_insert_to_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t *p_infr)
+{
+
+ OSM_LOG_ENTER( p_log, osm_infr_insert_to_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "Inserting a new InformInfo Record:\n");
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "Dump before insertion (size : %d) : \n",
+ cl_qlist_count(&p_subn->sa_infr_list) );
+ __dump_all_informs(p_subn, p_log);
+
+ /* osm_dump_inform_info(p_log,
+ &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG); */
+
+ cl_qlist_insert_head(&p_subn->sa_infr_list,
+ &p_infr->list_item);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "Dump after insertion (size : %d) : \n",
+ cl_qlist_count(&p_subn->sa_infr_list) );
+ __dump_all_informs(p_subn, p_log);
+ OSM_LOG_EXIT( p_log );
+}
+
+void
+osm_infr_remove_from_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_infr_t *p_infr)
+{
+ OSM_LOG_ENTER( p_log, osm_infr_remove_from_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_remove_from_db: "
+ "Removing InformInfo Subscribing GID:0x%016" PRIx64 ",0x%016" PRIx64
+ " Enum:0x%X from Database\n",
+ cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.prefix),
+ cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.interface_id),
+ p_infr->inform_record.subscriber_enum
+ );
+ osm_dump_inform_info(p_log, &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG);
+
+ cl_qlist_remove_item(&p_subn->sa_infr_list,
+ &p_infr->list_item);
+
+ osm_infr_destroy( p_infr );
+
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Send a report:
+ *
+ * Given a target address to send to and the notice.
+ * We need to send: SubnAdmReport - of SubnAdmClass
+ *
+ **********************************************************************/
+static
+ib_api_status_t
+osm_send_report(
+ IN osm_infr_t* p_infr_rec, /* the informinfo */
+ IN ib_mad_notice_attr_t* p_ntc /* notice to send */
+ ) {
+
+ osm_madw_t* p_report_madw;
+ ib_mad_notice_attr_t* p_report_ntc;
+ ib_mad_t* p_mad;
+ ib_sa_mad_t* p_sa_mad;
+ static atomic32_t trap_fwd_trans_id = 0x02DAB000;
+ ib_api_status_t status;
+ osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log;
+
+ OSM_LOG_ENTER( p_log, osm_send_report );
+
+ /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */
+
+ /* it is better to use LIDs since the GIDs might not be there for SMI traps */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_send_report: "
+ "Forwarding Notice Event from LID:0x%X"
+ " to InformInfo LID: 0x%X TID:0x%X\n",
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid),
+ trap_fwd_trans_id
+ );
+
+ /* get the MAD to send */
+ p_report_madw = osm_mad_pool_get( p_infr_rec->p_infr_rcv->p_mad_pool,
+ p_infr_rec->h_bind,
+ MAD_BLOCK_SIZE,
+ &(p_infr_rec->report_addr) );
+
+ p_report_madw->resp_expected = TRUE;
+
+ if( !p_report_madw )
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "osm_send_report: ERR 0203: "
+ "osm_mad_pool_get failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+ p_mad = osm_madw_get_mad_ptr( p_report_madw );
+ ib_mad_init_new(p_mad,
+ IB_MCLASS_SUBN_ADM,
+ 2,
+ IB_MAD_METHOD_REPORT,
+ cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+ IB_MAD_ATTR_NOTICE,
+ 0);
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_report_madw );
+
+ /* HACK: I'm not sure if we can simply use the SA MAD format for
+ notices. However, this is what is implied by the spec */
+ p_report_ntc = (ib_mad_notice_attr_t*)&(p_sa_mad->data);
+
+ /* copy the notice */
+ *p_report_ntc = *p_ntc;
+
+ /* The TRUE is for: response is expected */
+ status = osm_vendor_send(p_report_madw->h_bind, p_report_madw, TRUE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "osm_send_report: ERR 0204: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return(status);
+}
+
+/**********************************************************************
+ * This route comapre a given Notice and a ListItem of InformInfo type.
+ *
+ * PRE REQUISITES:
+ * The Notice.GID should be pre-filled with the trap generator GID
+ **********************************************************************/
+static
+void
+__match_notice_to_inf_rec(
+ IN cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ osm_infr_match_ctxt_t* p_infr_match = (osm_infr_match_ctxt_t *)context;
+ ib_mad_notice_attr_t* p_ntc = p_infr_match->p_ntc;
+ cl_list_t* p_infr_to_remove_list = p_infr_match->p_remove_infr_list;
+ osm_infr_t* p_infr_rec = (osm_infr_t*)p_list_item;
+ ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info);
+ cl_status_t status = CL_NOT_FOUND;
+ osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log;
+ osm_subn_t *p_subn = p_infr_rec->p_infr_rcv->p_subn;
+ ib_gid_t source_gid;
+ osm_port_t* p_src_port;
+ osm_port_t* p_dest_port;
+
+ OSM_LOG_ENTER( p_log, __match_notice_to_inf_rec );
+ /* matching rules
+ * InformInfo Notice
+ * GID IssuerGID if non zero must match the trap
+ * LIDRange IssuerLID apply only if GID=0
+ * IsGeneric IsGeneric is compulsory and must match the trap
+ * Type Type if not 0xFFFF must match
+ * TrapNumber TrapNumber if not 0xFFFF must match
+ * DeviceId DeviceID if not 0xFFFF must match
+ * QPN dont care
+ * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation
+ * VendorID VendorID match or 0xFFFFFF
+ */
+
+ /* GID IssuerGID if non zero must match the trap */
+ if (p_ii->gid.unicast.prefix != 0 || p_ii->gid.unicast.interface_id != 0 )
+ {
+ /* macth by GID */
+ if (cl_memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), sizeof(ib_gid_t)))
+ {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by GID\n");
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* LIDRange IssuerLID apply only if GID=0 */
+ /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */
+ if (p_ii->lid_range_begin != 0xFFFF)
+ {
+ /* a real lid range is given - check it. */
+ if ( (cl_hton16(p_ii->lid_range_begin) > cl_hton16(p_ntc->issuer_lid)) ||
+ (cl_hton16(p_ntc->issuer_lid) > cl_hton16(p_ii->lid_range_end)) ) {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by LID Range. Needed: 0x%X <= 0x%X <= 0x%X\n",
+ cl_hton16(p_ii->lid_range_begin),
+ cl_hton16(p_ntc->issuer_lid),
+ cl_hton16(p_ii->lid_range_end)
+ );
+ goto Exit;
+ }
+ }
+ }
+
+ /* IsGeneric IsGeneric is compulsory and must match the trap */
+ if ((p_ii->is_generic && ! ib_notice_is_generic(p_ntc)) ||
+ (!p_ii->is_generic && ib_notice_is_generic(p_ntc)))
+ {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Generic/Vendor\n");
+ goto Exit;
+ }
+
+ /* Type Type if not 0xFFFF must match */
+ if ((p_ii->trap_type != 0xFFFF) &&
+ (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Type\n");
+ goto Exit;
+ }
+
+ /* based on generic type */
+ if (p_ii->is_generic)
+ {
+ /* TrapNumber TrapNumber if not 0xFFFF must match */
+ if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) &&
+ (p_ii->g_or_v.generic.trap_num != p_ntc->g_or_v.generic.trap_num)) {
+
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Trap Num\n");
+ goto Exit;
+ }
+
+ /* ProducerType ProducerType match or 0xFFFFFF */
+ if ((cl_ntoh32(ib_inform_info_get_node_type(p_ii)) != 0xFFFFFF) &&
+ (ib_inform_info_get_node_type(p_ii) != ib_notice_get_prod_type(p_ntc))) {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Node Type: II=0x%06X Trap=0x%06X\n",
+ cl_ntoh32(ib_inform_info_get_node_type(p_ii)),
+ cl_ntoh32(ib_notice_get_prod_type(p_ntc))
+ );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* DeviceId DeviceID if not 0xFFFF must match */
+ if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) &&
+ (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Dev Id\n");
+ goto Exit;
+ }
+
+ /* VendorID VendorID match or 0xFFFFFF */
+ if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) &&
+ (ib_inform_info_get_vend_id(p_ii) != ib_notice_get_vend_id(p_ntc))) {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Vendor ID\n");
+
+ goto Exit;
+ }
+ }
+
+ /* Check if there is a pkey match. o13-17.1.1*/
+ /* Check if the issuer of the trap is the SM. If it is, then the gid
+ comparison should be done on the trap source (saved as the gid in the
+ data details field).
+ If the issuer gid is not the SM - then it is the guid of the trap
+ source. */
+ if ( (cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == p_subn->opt.subnet_prefix) &&
+ (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == p_subn->sm_port_guid) )
+ {
+ /* The issuer is the SM then this is trap 64-67 - compare the gid
+ with the gid saved on the data details. */
+ source_gid = p_ntc->data_details.ntc_64_67.gid;
+ }
+ else
+ {
+ source_gid = p_ntc->issuer_gid;
+ }
+ p_src_port = (osm_port_t*)cl_qmap_get( &p_subn->port_guid_tbl,
+ source_gid.unicast.interface_id );
+
+ if( p_src_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
+ {
+ osm_log(p_log, OSM_LOG_INFO,
+ "__match_notice_to_inf_rec: "
+ "Cannot find source port with GUID:0x%016" PRIx64 "\n",
+ cl_ntoh64(source_gid.unicast.interface_id) );
+ goto Exit;
+ }
+
+ p_dest_port =
+ cl_ptr_vector_get( &p_subn->port_lid_tbl,
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+ if( !p_dest_port )
+ {
+ osm_log(p_log, OSM_LOG_INFO,
+ "__match_notice_to_inf_rec: "
+ "Cannot find destination port with LID:0x%04x\n",
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+ goto Exit;
+ }
+
+ if (osm_port_share_pkey( p_log, p_src_port, p_dest_port ) == FALSE )
+ {
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Pkey\n");
+ /* According to o13-17.1.2 - If this informInfo does not have
+ lid_range_begin of 0xFFFF, then this informInfo request
+ should be removed from database. */
+ if (p_ii->lid_range_begin != 0xFFFF)
+ {
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "__match_notice_to_inf_rec: "
+ "Pkey mismatch on lid_range_begin != 0xFFFF. "
+ "Need to remove this informInfo from db.\n");
+ /* add the informInfo record to the remove_infr list. */
+ cl_list_insert_tail( p_infr_to_remove_list,
+ p_infr_rec );
+ }
+ goto Exit;
+ }
+
+ /* send the report to the address provided in the inform record */
+ osm_log(p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "MATCH! Sending Report...\n");
+ osm_send_report(p_infr_rec, p_ntc);
+ status = CL_SUCCESS;
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Once a Trap was received by the osm_trap_rcv, or a Trap sourced in
+ * the SM was sent (Traps 64-67) this routine is called with a copy of
+ * the notice data.
+ * Given a notice attribute - compare and see if it matches the InformInfo
+ * Element and if it does - call the Report(Notice) for the
+ * target QP registered by the address stored in the InformInfo element
+ **********************************************************************/
+ib_api_status_t
+osm_report_notice(
+ IN osm_log_t* const p_log,
+ IN osm_subn_t* p_subn,
+ IN ib_mad_notice_attr_t *p_ntc
+ ) {
+
+ osm_infr_match_ctxt_t context;
+ cl_list_t infr_to_remove_list;
+ osm_infr_t* p_infr_rec;
+ osm_infr_t* p_next_infr_rec;
+
+ OSM_LOG_ENTER( p_log, osm_report_notice );
+
+ /*
+ * we must make sure we are ready for this ...
+ * note that the trap receivers might be initialized before
+ * the osm_infr_init call is performed.
+ */
+ if (p_subn->sa_infr_list.state != CL_INITIALIZED)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_report_notice: "
+ "Ignoring Notice Reports since Inform List is not initialized yet!\n");
+ return IB_ERROR;
+ }
+
+ /* an official Event information log */
+ if (ib_notice_is_generic(p_ntc))
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "osm_report_notice: "
+ "Reporting Generic Notice type:%u num:%u"
+ " from LID:0x%04X GID:0x%016" PRIx64
+ ",0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntc),
+ cl_ntoh16(p_ntc->g_or_v.generic.trap_num),
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+ );
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "osm_report_notice: "
+ "Reporting Vendor Notice type:%u vend:%u dev:%u"
+ " from LID:0x%04X GID:0x%016" PRIx64
+ ",0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntc),
+ cl_ntoh32(ib_notice_get_vend_id(p_ntc)),
+ cl_ntoh16(p_ntc->g_or_v.vend.dev_id),
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+ );
+ }
+
+ /* Create a list that will hold all the infr records that should
+ be removed due to violation. o13-17.1.2 */
+ cl_list_construct( &infr_to_remove_list );
+ cl_list_init( &infr_to_remove_list, 5 );
+ context.p_remove_infr_list = &infr_to_remove_list;
+ context.p_ntc = p_ntc;
+
+ /* go over all inform info available at the subnet */
+ /* try match to the given notice and send if match */
+ cl_qlist_apply_func(&(p_subn->sa_infr_list),
+ __match_notice_to_inf_rec,
+ &context );
+
+ /* If we inserted items into the infr_to_remove_list - we need to
+ remove them. */
+ p_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list);
+ while ( p_infr_rec != NULL )
+ {
+ p_next_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list);
+ osm_infr_remove_from_db ( p_subn, p_log, p_infr_rec );
+ p_infr_rec = p_next_infr_rec;
+ }
+ cl_list_destroy(&infr_to_remove_list);
+
+ OSM_LOG_EXIT( p_log );
+
+ return(IB_SUCCESS);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Implementation of osm_lid_mgr_t.
+ * This file implements the LID Manager object which is responsible for
+ * assigning LIDs to all ports on the subnet.
+ *
+ * DATA STRUCTURES:
+ * p_subn->port_lid_tbl : a vector pointing from lid to its port.
+ * osm db guid2lid domain : a hash from guid to lid (min lid)
+ * p_subn->port_guid_tbl : a map from guid to discovered port obj.
+ *
+ * ALGORITHM:
+ *
+ * 0. we define a function to obtain the correct port lid:
+ * __osm_lid_mgr_get_port_lid( p_mgr, port, &min_lid ):
+ * 0.1 if the port info lid matches the guid2lid return 0
+ * 0.2 if the port info has a lid and that range is empty in
+ * port_lid_tbl - return 0 and update the port_lid_tbl and
+ * guid2lid
+ * 0.3 else find an empty space in port_lid_tbl, update the
+ * port_lid_tbl and guid2lid, return 1 - to flag a change required.
+ *
+ * 1. During initialization:
+ * 1.1 initialize the guid2lid database domain.
+ * 1.2 if reassign_lid is not set:
+ * 1.2.1 read the persistant data for the domain.
+ * 1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1)
+ *
+ * 2. During SM port lid assignment:
+ * 2.1 if reassign_lids is set - make it 2^lmc
+ * 2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid
+ * 2.3 call __osm_lid_mgr_get_port_lid the SM port
+ * 2.4 set the port info
+ *
+ * 3. During all other ports lid assignment:
+ * 3.1 go through all ports in the subnet.
+ * 3.1.1 call __osm_lid_mgr_get_port_min_lid
+ * 3.1.2 if a change required send the port info
+ * 3.2 if any change send the signal PENDING...
+ *
+ * 4. Store the guid2lid
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_db_pack.h>
+#include <stdlib.h>
+
+/**********************************************************************
+ lid range item of qlist
+ **********************************************************************/
+typedef struct _osm_lid_mgr_range {
+ cl_list_item_t item;
+ uint16_t min_lid;
+ uint16_t max_lid;
+} osm_lid_mgr_range_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_mgr_construct(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof(*p_mgr) );
+ cl_ptr_vector_construct( &p_mgr->used_lids );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_mgr_destroy(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ cl_list_item_t *p_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_destroy );
+
+ cl_ptr_vector_destroy( &p_mgr->used_lids );
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+ {
+ cl_free((osm_lid_mgr_range_t *)p_item);
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ }
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+Validate the guid to lid data by making sure that under the current
+LMC we did not get duplicates. If we do flag them as errors and remove
+the entry.
+**********************************************************************/
+void
+__osm_lid_mgr_validate_db(
+ IN osm_lid_mgr_t* p_mgr)
+{
+ cl_qlist_t guids;
+ osm_db_guid_elem_t *p_item;
+ uint16_t lid;
+ uint16_t min_lid;
+ uint16_t max_lid;
+ uint16_t lmc_mask;
+ boolean_t lids_ok;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_validate_db );
+
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+
+ else
+ lmc_mask = 0xffff;
+
+ cl_qlist_init( &guids );
+
+ if (osm_db_guid2lid_guids( p_mgr->p_g2l, &guids ))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0310: "
+ "could not get guid list.\n");
+ goto Exit;
+ }
+
+ p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+ while ((cl_list_item_t*)p_item != cl_qlist_end(&guids))
+ {
+ if (osm_db_guid2lid_get( p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid ))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0311: "
+ "could not get lid for guid:0x%016" PRIx64".\n",
+ p_item->guid
+ );
+ }
+ else
+ {
+ lids_ok = TRUE;
+
+ if ((min_lid > max_lid) || (min_lid == 0) || (p_item->guid == 0) ||
+ (max_lid > p_mgr->p_subn->max_unicast_lid_ho))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0312: "
+ "Illegal LID range [0x%x:0x%x] for guid:0x%016" PRIx64
+ ".\n",
+ min_lid, max_lid, p_item->guid
+ );
+ lids_ok = FALSE;
+ }
+ else if ((min_lid != max_lid) && ((min_lid & lmc_mask) != min_lid))
+ {
+ /* check that if the lids define a range - that range is valid
+ for the current LMC mask */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0313: "
+ "LID range [0x%x:0x%x] for guid:0x%016" PRIx64
+ " is not aligned acording to mask:0x%04x.\n",
+ min_lid, max_lid, p_item->guid, lmc_mask
+ );
+ lids_ok = FALSE;
+ }
+ else
+ {
+ /* check if the lids were not previously assigend */
+ for (lid = min_lid; lid <= max_lid; lid++)
+ {
+ if (( cl_ptr_vector_get_size( &p_mgr->used_lids ) > lid ) &&
+ ( cl_ptr_vector_get( &p_mgr->used_lids, lid ) ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0314: "
+ "0x%04x for guid:0x%016" PRIx64
+ " was previously used.\n",
+ lid, p_item->guid
+ );
+ lids_ok = FALSE;
+ }
+ }
+ }
+
+ if (!lids_ok)
+ {
+ if (osm_db_guid2lid_delete( p_mgr->p_g2l, p_item->guid ))
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0315: "
+ "failed to delete entry for guid:0x%016" PRIx64
+ " .\n",
+ p_item->guid
+ );
+ }
+ else
+ {
+ /* mark it was visited */
+ for (lid = min_lid; lid <= max_lid; lid++)
+ cl_ptr_vector_set( &p_mgr->used_lids, lid, (void *)1);
+ }
+ } /* got a lid */
+ p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+ } /* all guids */
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_mgr_init(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lid_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+ CL_ASSERT( p_db );
+
+ osm_lid_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_db = p_db;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ /* we initialize and restore the db domain of guid to lid map */
+ p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid");
+ if (! p_mgr->p_g2l)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_lid_mgr_init: ERR 0316: "
+ "Error initializing Guid-to-Lid persistant database.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ cl_ptr_vector_init( &p_mgr->used_lids, 100, 40 );
+ cl_qlist_init( &p_mgr->free_ranges );
+
+ /* we use the stored guid to lid table if not forced to re-assign */
+ if (!p_mgr->p_subn->opt.reassign_lids)
+ {
+ if (osm_db_restore(p_mgr->p_g2l))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_lid_mgr_init: ERR 0317: "
+ "Error restoring Guid-to-Lid persistant database.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* we need to make sure we did not get duplicates with
+ current lmc */
+ __osm_lid_mgr_validate_db(p_mgr);
+ }
+
+Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ initialize the manager for a new sweep:
+ scans the known persistent assignment and port_lid_tbl
+ re-calculate all empty ranges.
+ cleanup invalid port_lid_tbl entries
+**********************************************************************/
+int
+__osm_lid_mgr_init_sweep(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+
+ cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
+ cl_ptr_vector_t *p_persistent_vec = &p_mgr->used_lids;
+ uint16_t max_defined_lid;
+ uint16_t max_persistent_lid;
+ uint16_t max_discovered_lid;
+ uint16_t lid, l;
+ uint16_t disc_min_lid;
+ uint16_t disc_max_lid;
+ uint16_t db_min_lid;
+ uint16_t db_max_lid;
+ int status = 0;
+ cl_list_item_t *p_item;
+ boolean_t is_free;
+ osm_lid_mgr_range_t *p_range = NULL;
+ osm_port_t *p_port;
+ cl_qmap_t *p_port_guid_tbl;
+ uint8_t lmc_num_lids = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );
+
+ /* if we came out of standby we need to discard any previous guid 2 lid
+ info we might had */
+ if ( p_mgr->p_subn->coming_out_of_standby == TRUE )
+ {
+ osm_db_clear( p_mgr->p_g2l );
+ for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++)
+ cl_ptr_vector_set(&p_mgr->used_lids, lid, NULL);
+ }
+
+ /* we need to cleanup the empty ranges list */
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+ {
+ cl_free( (osm_lid_mgr_range_t *)p_item );
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ }
+
+ /* first clean up the port_by_lid_tbl */
+ for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++)
+ cl_ptr_vector_set(p_discovered_vec, lid, NULL);
+
+ /* we if are on the first sweep and in re-assign lids mode
+ we should ignore all the available info and simply define one
+ hufe empty range */
+ if ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
+ (p_mgr->p_subn->opt.reassign_lids == TRUE ))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "Skipping all lids - as we are reassigning them.\n");
+ p_range =
+ (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
+ p_range->min_lid = 1;
+ goto AfterScanningLids;
+ }
+
+ /* go over all discvered ports and mark their entries */
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+ p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+ {
+ osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+ for (lid = disc_min_lid; lid <= disc_max_lid; lid++)
+ cl_ptr_vector_set(p_discovered_vec, lid, p_port );
+ }
+
+ /*
+ Our task is to find free lid ranges.
+ A lid can be used if
+ 1. a persistent assignment exists
+ 2. the lid is used by a discovered port that does not have a persistent
+ assignment.
+
+ scan through all lid values of both the persistent table and
+ discovered table.
+ If the lid has an assigned port in the discovered table:
+ * make sure the lid matches the persistent table, or
+ * there is no other persistent assignment for that lid.
+ * else cleanup the port_by_lid_tbl, mark this as empty range.
+ Else if the lid does not have an entry in the persistent table
+ mark it as free.
+ */
+
+ /* find the range of lids to scan */
+ max_discovered_lid = (uint16_t)cl_ptr_vector_get_size(p_discovered_vec);
+ max_persistent_lid = (uint16_t)cl_ptr_vector_get_size(p_persistent_vec);
+
+ /* but the vectors have one extra entry for lid=0 */
+ if (max_discovered_lid) max_discovered_lid--;
+ if (max_persistent_lid) max_persistent_lid--;
+
+ if (max_persistent_lid > max_discovered_lid)
+ max_defined_lid = max_persistent_lid;
+ else
+ max_defined_lid = max_discovered_lid;
+
+ for (lid = 1; lid <= max_defined_lid ; lid++)
+ {
+ is_free = TRUE;
+ /* first check to see if the lid is used by a persistent assignment */
+ if ((lid < max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "0x%04x is not free as its mapped by the persistent db.\n",
+ lid);
+ is_free = FALSE;
+ }
+
+ /* check the discovered port if there is one */
+ if ((lid < max_discovered_lid) &&
+ (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))
+ {
+ /* get the lid range of that port - but we know how many lids we
+ are about to assign to it */
+ osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+ if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=
+ IB_NODE_TYPE_SWITCH)
+ disc_max_lid = disc_min_lid + lmc_num_lids - 1;
+
+ /* qualify the guid of the port is not persistently mapped to
+ another range */
+ if (!osm_db_guid2lid_get( p_mgr->p_g2l,
+ cl_ntoh64(osm_port_get_guid(p_port)),
+ &db_min_lid, &db_max_lid))
+ {
+ /* ok there is an asignment - is it the same ? */
+ if ((disc_min_lid == db_min_lid) && (disc_max_lid == db_max_lid))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "[0x%04x,0x%04x] is not free as it was discovered "
+ " and mapped by the persistent db.\n",
+ disc_min_lid, disc_max_lid);
+ is_free = FALSE;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "[0x%04x,0x%04x] is free as it was discovered"
+ " but mapped to range: [0x%x:0x%x] by the persistent db.\n",
+ disc_min_lid, disc_max_lid, db_min_lid, db_max_lid);
+ for (l = disc_min_lid; l <= disc_max_lid; l++)
+ cl_ptr_vector_set(p_discovered_vec, l, NULL);
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "0x%04x is not free as it was discovered"
+ " and there is no persistent db entry for it.\n",
+ lid);
+ is_free = FALSE;
+ }
+
+ /* if there is more then one lid on that port - and the discovered port
+ is going to retain its lids advance to the max lid */
+ if (is_free == FALSE)
+ {
+ lid = disc_max_lid;
+ }
+ }
+
+ if (is_free)
+ {
+ if (p_range)
+ {
+ p_range->max_lid = lid;
+ }
+ else
+ {
+ p_range =
+ (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
+ p_range->min_lid = lid;
+ p_range->max_lid = lid;
+ }
+ }
+ else
+ {
+ /* this lid is used so we need to finalize the previous free range */
+ if (p_range)
+ {
+ cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "new free lid range [0x%x:0x%x]\n",
+ p_range->min_lid, p_range->max_lid);
+ p_range = NULL;
+ }
+ }
+ }
+
+ AfterScanningLids:
+ /* after scanning all known lids we need to extend the last range
+ to the max allowed lid */
+ if (!p_range)
+ {
+ p_range =
+ (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
+ p_range->min_lid = 1;
+ }
+ p_range->max_lid = p_mgr->p_subn->max_unicast_lid_ho - 1;
+ cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "final free lid range [0x%x:0x%x]\n",
+ p_range->min_lid, p_range->max_lid);
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return status;
+}
+
+/**********************************************************************
+ check if the given range of lids is free
+**********************************************************************/
+static boolean_t
+__osm_lid_mgr_is_range_not_persistent(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN const uint16_t lid,
+ IN const uint16_t num_lids )
+{
+ uint16_t i;
+ cl_status_t status;
+ osm_port_t *p_port;
+ const uint8_t start_lid = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
+ const cl_ptr_vector_t* const p_tbl = &p_mgr->used_lids;
+
+ if( lid < start_lid )
+ return( FALSE );
+
+ for( i = lid; i < lid + num_lids; i++ )
+ {
+ status = cl_ptr_vector_at( p_tbl, i, (void*)&p_port );
+ if( status == CL_SUCCESS )
+ {
+ if(p_port != NULL)
+ return( FALSE );
+ }
+ else
+ {
+ /*
+ We are out of range in the array.
+ Consider all further entries "free".
+ */
+ return( TRUE );
+ }
+ }
+
+ return( TRUE );
+}
+
+/**********************************************************************
+find a free lid range
+**********************************************************************/
+static void
+__osm_lid_mgr_find_free_lid_range(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN const uint8_t num_lids,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const p_max_lid )
+{
+ uint16_t lid;
+ cl_list_item_t *p_item;
+ cl_list_item_t *p_next_item;
+ osm_lid_mgr_range_t *p_range = NULL;
+ uint8_t lmc_num_lids;
+ uint16_t lmc_mask;
+
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_find_free_lid_range: "
+ "LMC = %u, number LIDs = %u.\n",
+ p_mgr->p_subn->opt.lmc, num_lids );
+
+ lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc );
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ /*
+ Search the list of free lid ranges for a range which is big enough
+ */
+ p_item = cl_qlist_head( &p_mgr->free_ranges );
+ while( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+ {
+ p_next_item = cl_qlist_next( p_item );
+ p_range = (osm_lid_mgr_range_t *)p_item;
+
+ lid = p_range->min_lid;
+
+ /* if we require more then one lid we must align to LMC */
+ if (num_lids > 1)
+ {
+ if ((lid & lmc_mask) != lid)
+ lid = (lid + lmc_num_lids) & lmc_mask;
+ }
+
+ /* but we can be out of the range */
+ if (lid + num_lids - 1 <= p_range->max_lid)
+ {
+ /* ok let us use that range */
+ if (lid + num_lids - 1 == p_range->max_lid)
+ {
+ /* we consumed the entire range */
+ cl_qlist_remove_item( &p_mgr->free_ranges, p_item );
+ }
+ else
+ {
+ /* only update the available range */
+ p_range->min_lid = lid + num_lids;
+ }
+
+ *p_min_lid = lid;
+ *p_max_lid = (uint16_t)(lid + num_lids - 1);
+ return;
+ }
+ p_item = p_next_item;
+ }
+
+ /*
+ Couldn't find a free range of lids.
+ */
+ *p_min_lid = *p_max_lid = 0;
+ /* if we run out of lids - give an error and abort! */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_find_free_lid_range: ERR 0307: "
+ "OPENSM RAN OUT OF LIDS!!!\n");
+ CL_ASSERT( 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ __osm_lid_mgr_cleanup_discovered_port_lid_range(
+ IN osm_lid_mgr_t* p_mgr,
+ IN osm_port_t *p_port )
+{
+ cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
+ uint16_t lid, min_lid, max_lid;
+ uint16_t max_tbl_lid = (uint16_t)(cl_ptr_vector_get_size( p_discovered_vec ));
+
+ osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
+ for (lid = min_lid; lid <= max_lid; lid++)
+ {
+ if ((lid < max_tbl_lid ) &&
+ (p_port == (osm_port_t*)cl_ptr_vector_get(p_discovered_vec, lid)))
+ cl_ptr_vector_set(p_discovered_vec, lid, NULL );
+ }
+}
+
+/**********************************************************************
+ 0.1 if the port info lid matches the guid2lid return 0
+ 0.2 if the port info has a lid and that range is empty in
+ port_lid_tbl - return 0 and update the port_lid_tbl and
+ guid2lid
+ 0.3 else find an empty space in port_lid_tbl, update the
+ port_lid_tbl and guid2lid, return 1 - to flag a change required.
+**********************************************************************/
+int
+__osm_lid_mgr_get_port_lid(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN osm_port_t * const p_port,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const p_max_lid)
+{
+ uint16_t lid, min_lid, max_lid;
+ uint64_t guid;
+ uint8_t num_lids = (1 << p_mgr->p_subn->opt.lmc);
+ int lid_changed = 0;
+ uint16_t lmc_mask;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_get_port_lid );
+
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ /* get the lid from the guid2lid */
+ guid = cl_ntoh64( osm_port_get_guid( p_port ) );
+
+ /* if the port is a switch then we only need one lid */
+ if( osm_node_get_type( osm_port_get_parent_node( p_port ) ) ==
+ IB_NODE_TYPE_SWITCH )
+ num_lids = 1;
+
+ /* if the port matches the guid2lid */
+ if (!osm_db_guid2lid_get( p_mgr->p_g2l, guid, &min_lid, &max_lid))
+ {
+ *p_min_lid = min_lid;
+ *p_max_lid = min_lid + num_lids - 1;
+ if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port)))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" matches its known lid:0x%04x\n",
+ guid, min_lid);
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " with lid:0x%04x does not matches its known lid:0x%04x\n",
+ guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid);
+ __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
+ /* we still need to send the setting to the target port */
+ lid_changed = 1;
+ goto Exit;
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" has no persistent lid assigned.\n",
+ guid);
+ }
+
+ /* if the port info carries a lid it must be lmc aligned and not mapped
+ by the pesistent storage */
+ min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
+
+ /* we want to ignore the discovered lid if we are also on first sweep of
+ re-assign lids flow */
+ if (min_lid &&
+ ! ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
+ (p_mgr->p_subn->opt.reassign_lids == TRUE )))
+ {
+ /* make sure lid is valid */
+ if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid))
+ {
+ /* is it free */
+ if (__osm_lid_mgr_is_range_not_persistent(p_mgr, min_lid, num_lids))
+ {
+ *p_min_lid = min_lid;
+ *p_max_lid = min_lid + num_lids - 1;
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" lid range:[0x%x-0x%x] is free\n",
+ guid, *p_min_lid, *p_max_lid);
+ goto NewLidSet;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " existing lid range:[0x%x:0x%x] is not free.\n",
+ guid, min_lid, min_lid + num_lids - 1);
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " existing lid range:[0x%x:0x%x] is not lmc aligned.\n",
+ guid, min_lid, min_lid + num_lids - 1);
+ }
+ }
+
+ /* first cleanup the existing discovered lid range */
+ __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
+
+ /* find an empty space */
+ __osm_lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid);
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" assigned a new lid range:[0x%x-0x%x]\n",
+ guid, *p_min_lid, *p_max_lid);
+ lid_changed = 1;
+
+ NewLidSet:
+ /* update the guid2lid db and used_lids */
+ osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid);
+ for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
+ cl_ptr_vector_set(&p_mgr->used_lids, lid, (void*)1);
+
+ Exit:
+ /* make sure the assigned lids are marked in port_lid_tbl */
+ for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
+ cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port);
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return lid_changed;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_lid_mgr_set_physp_pi(
+ IN osm_lid_mgr_t * const p_mgr,
+ IN osm_physp_t* const p_physp,
+ IN ib_net16_t const lid )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_port_info_t* p_pi = (ib_port_info_t*)payload;
+ const ib_port_info_t* p_old_pi;
+ osm_madw_context_t context;
+ osm_node_t* p_node;
+ ib_api_status_t status;
+ uint8_t mtu;
+ uint8_t op_vls;
+ uint8_t port_num;
+ boolean_t send_set = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_set_physp_pi );
+
+ /*
+ Don't bother doing anything if this Physical Port is not valid.
+ This allows simplified code in the caller.
+ */
+ if( p_physp == NULL )
+ goto Exit;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ goto Exit;
+
+ port_num = osm_physp_get_port_num( p_physp );
+ p_node = osm_physp_get_node_ptr( p_physp );
+
+ if( (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) &&
+ (port_num != 0) )
+ {
+ /*
+ Switches ports that are not 0 - should not be set with the
+ following attributes set later (during NO_CHANGE state in link mgr).
+ */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_set_physp_pi: "
+ "Skipping switch port %u, GUID = 0x%016" PRIx64 ".\n",
+ port_num,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ goto Exit;
+ }
+
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /*
+ First, copy existing parameters from the PortInfo attribute we
+ already have for this node.
+
+ Second, update with default values that we know must be set for
+ every Physical Port and the LID and set the neighbor MTU field
+ appropriately.
+
+ Third, send the SMP to this physical port.
+ */
+
+ cl_memclr( payload, IB_SMP_DATA_SIZE );
+
+ /* Correction by FUJITSU */
+ if( port_num != 0 )
+ {
+ cl_memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+ }
+
+ /*
+ Correction following a bug injected by the previous
+ FUJITSU line:
+
+ Should never write back a value that is bigger then 3 in
+ the PortPhysicalState field - so can not simply copy!
+
+ Actually we want to write there:
+ port physical state - no change,
+ link down default state = polling
+ port state - no change
+ */
+ /* these values can be set only for hca ports, so if we are
+ on a switch node - set these values to zero */
+ if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ p_pi->state_info2 = 0x0;
+ else
+ {
+ p_pi->state_info2 = 0x02;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if ( ib_port_info_get_link_down_def_state(p_pi) !=
+ ib_port_info_get_link_down_def_state(p_old_pi) )
+ send_set = TRUE;
+ }
+
+ ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+
+ p_pi->m_key = p_mgr->p_subn->opt.m_key;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
+ send_set = TRUE;
+
+ p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
+ sizeof(p_pi->subnet_prefix) ))
+ send_set = TRUE;
+
+ p_pi->base_lid = lid;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
+ sizeof(p_pi->base_lid) ))
+ send_set = TRUE;
+
+ /* we are updating the ports with our local sm_base_lid */
+ p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
+ sizeof(p_pi->master_sm_base_lid) ))
+ send_set = TRUE;
+
+ p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period,
+ sizeof(p_pi->m_key_lease_period) ))
+ send_set = TRUE;
+
+ /*
+ we want to set the timeout for both the switch port 0
+ and the HCA ports
+ */
+ ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
+ send_set = TRUE;
+
+ if( port_num != 0 )
+ {
+ /*
+ HCA's don't have a port 0, and for switch port 0,
+ the state bits are ignored.
+ This is not the switch management port
+ */
+ p_pi->link_width_enabled = p_old_pi->link_width_supported;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
+ sizeof(p_pi->link_width_enabled) ))
+ send_set = TRUE;
+
+ /* M_KeyProtectBits are always zero */
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is - turn on send_set flag */
+ if (cl_memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+ send_set = TRUE;
+
+ /* calc new op_vls and mtu */
+ op_vls = osm_physp_calc_link_op_vls(
+ p_mgr->p_log, p_mgr->p_subn, p_physp );
+ mtu = osm_physp_calc_link_mtu(p_mgr->p_log, p_physp );
+
+ ib_port_info_set_neighbor_mtu( p_pi, mtu );
+
+ if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+ ib_port_info_get_neighbor_mtu(p_old_pi) )
+ send_set = TRUE;
+
+ ib_port_info_set_op_vls( p_pi, op_vls );
+ if ( ib_port_info_get_op_vls(p_pi) !=
+ ib_port_info_get_op_vls(p_old_pi) )
+ send_set = TRUE;
+
+ /*
+ Several timeout mechanisms:
+ */
+ ib_port_info_set_phy_and_overrun_err_thd(
+ p_pi,
+ p_mgr->p_subn->opt.local_phy_errors_threshold,
+ p_mgr->p_subn->opt.overrun_errors_threshold);
+
+ if (cl_memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold,
+ sizeof(p_pi->error_threshold) ))
+ send_set = TRUE;
+
+ /*
+ TO DO -
+ If the subnet is being reconfigured, should we force the link
+ to the INIT state?
+
+ To reset the port state machine we can send PortInfo.State = DOWN.
+ (see: 7.2.7 p161 lines:10-19.)
+ */
+ if ( (mtu != ib_port_info_get_mtu_cap( p_old_pi )) ||
+ (op_vls != ib_port_info_get_op_vls(p_old_pi)))
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_set_physp_pi: "
+ "Sending Link Down due to op_vls or mtu change. MTU:%u,%u VL_CAP:%u,%u \n",
+ mtu, ib_port_info_get_mtu_cap( p_old_pi ),
+ op_vls, ib_port_info_get_op_vls(p_old_pi)
+ );
+ }
+ ib_port_info_set_port_state( p_pi, IB_LINK_DOWN );
+ if ( ib_port_info_get_port_state(p_pi) !=
+ ib_port_info_get_port_state(p_old_pi) )
+ send_set = TRUE;
+ }
+ }
+ else
+ {
+ /*
+ For Port 0 - NeighborMTU is relevant only for Enh. SP0.
+ In this case we'll set the MTU according to the mtu_cap
+ */
+ ib_port_info_set_neighbor_mtu( p_pi, ib_port_info_get_mtu_cap( p_old_pi ) );
+ if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+ ib_port_info_get_neighbor_mtu(p_old_pi) )
+ send_set = TRUE;
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_set_physp_pi: "
+ "Updating neighbor_mtu on sw. port 0 to:%u\n",
+ ib_port_info_get_neighbor_mtu( p_pi ) );
+ }
+
+ context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+ context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+ context.pi_context.set_method = TRUE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ /*
+ We need to set the cli_rereg bit when we are in first_time_master_sweep for
+ ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11
+ */
+ if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE ) &&
+ ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) )
+ ib_port_info_set_client_rereg( p_pi, 1 );
+
+ /* We need to send the PortInfoSet request with the new sm_lid
+ in the following cases:
+ 1. There is a change in the values (send_set == TRUE)
+ 2. first_time_master_sweep flag on the subnet is TRUE. This means the
+ SM just became master, and it then needs to send at PortInfoSet to
+ every port.
+ 3. got_set_resp on the physical port is FALSE. This means we haven't seen
+ this port before - need to send Set of PortInfo to it.
+ */
+ if (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+ p_physp->got_set_resp == FALSE)
+ {
+
+ p_mgr->send_set_reqs = TRUE;
+ status = osm_req_set( p_mgr->p_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ payload,
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32(osm_physp_get_port_num( p_physp )),
+ CL_DISP_MSGID_NONE,
+ &context );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+ p_physp->got_set_resp == FALSE);
+}
+
+/**********************************************************************
+ Processes our own node
+ Lock must already be held.
+**********************************************************************/
+static boolean_t
+__osm_lid_mgr_process_our_sm_node(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_port_t *p_port;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ osm_physp_t *p_physp;
+ boolean_t res = TRUE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_process_our_sm_node );
+
+ /*
+ Acquire our own port object.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( &p_mgr->p_subn->port_guid_tbl,
+ p_mgr->p_subn->sm_port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( &p_mgr->p_subn->port_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_process_our_sm_node: ERR 0308: "
+ "Can't acquire SM's Port object, GUID = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_mgr->p_subn->sm_port_guid ) );
+ res = FALSE;
+ goto Exit;
+ }
+
+ /*
+ Determine the LID this SM will use for its own port.
+ Be careful. With an LMC > 0, the bottom of the LID range becomes
+ unusable, since port hardware will mask off least significant bits,
+ leaving a LID of 0 (invalid). Therefore, make sure that we always
+ configure the SM with a LID that has non-zero bits, even after
+ LMC masking by hardware.
+ */
+ __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_process_our_sm_node: "
+ "Current base LID is 0x%X.\n", min_lid_ho );
+ /*
+ Update subnet object.
+ */
+ p_mgr->p_subn->master_sm_base_lid = cl_hton16( min_lid_ho );
+ p_mgr->p_subn->sm_base_lid = cl_hton16( min_lid_ho );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_lid_mgr_process_our_sm_node: "
+ "Assigning SM's port 0x%016" PRIx64
+ "\n\t\t\t\tto LID range [0x%X,0x%X].\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ min_lid_ho, max_lid_ho );
+ }
+
+ /*
+ Set the PortInfo the Physical Port associated
+ with this Port.
+ */
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+
+ __osm_lid_mgr_set_physp_pi( p_mgr, p_physp, cl_hton16( min_lid_ho ) );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return res;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_sm(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_signal_t signal = OSM_SIGNAL_DONE_PENDING;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_sm );
+
+ CL_ASSERT( p_mgr->p_subn->sm_port_guid );
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ /* initialize the port_lid_tbl and empty ranges list following the
+ persistant db */
+ __osm_lid_mgr_init_sweep( p_mgr );
+
+ if (p_mgr->p_subn->opt.pfn_ui_pre_lid_assign)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_lid_mgr_process_sm: "
+ "Invoking UI function pfn_ui_pre_lid_assign\n");
+ p_mgr->p_subn->opt.pfn_ui_pre_lid_assign(
+ p_mgr->p_subn->opt.ui_pre_lid_assign_ctx);
+ }
+
+ /* Set the send_set_reqs of the p_mgr to FALSE, and
+ we'll see if any set requests were sent. If not -
+ can signal OSM_SIGNAL_DONE */
+ p_mgr->send_set_reqs = FALSE;
+ if ( __osm_lid_mgr_process_our_sm_node( p_mgr ) == FALSE )
+ /* The initialization failed */
+ signal = OSM_SIGNAL_DONE;
+
+ if ( p_mgr->send_set_reqs == FALSE )
+ signal = OSM_SIGNAL_DONE;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ 1 go through all ports in the subnet.
+ 1.1 call __osm_lid_mgr_get_port_min_lid
+ 1.2 if a change is required send the port info
+ 2 if any change send the signal PENDING...
+**********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_signal_t signal;
+ cl_qmap_t *p_port_guid_tbl;
+ osm_port_t *p_port;
+ ib_net64_t port_guid;
+ uint16_t min_lid_ho, max_lid_ho;
+ osm_physp_t *p_physp;
+ int lid_changed;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet );
+
+ CL_ASSERT( p_mgr );
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ CL_ASSERT( p_mgr->p_subn->sm_port_guid );
+
+ /* Set the send_set_reqs of the p_mgr to FALSE, and
+ we'll see if any set requests were sent. If not -
+ can signal OSM_SIGNAL_DONE */
+ p_mgr->send_set_reqs = FALSE;
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+ p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+ {
+ port_guid = osm_port_get_guid( p_port );
+
+ /*
+ Our own port is a special case in that we want to
+ assign a LID to ourselves first, since we have to
+ advertise that LID value to the other ports.
+
+ For that reason, our node is treated separately and
+ we will not add it to any of these lists.
+ */
+ if( port_guid == p_mgr->p_subn->sm_port_guid )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_lid_mgr_process_subnet: "
+ "Skipping our own port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ }
+ else
+ {
+ /*
+ get the port lid range - we need to send it on first active sweep or
+ if there was a change (the result of the __osm_lid_mgr_get_port_lid)
+ */
+ lid_changed =
+ __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
+
+ /* we can call the function to update the port info as it known to
+ look for any field change and will only send an updated if required */
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_lid_mgr_process_subnet: "
+ "Assigned port 0x%016" PRIx64
+ ", LID [0x%X,0x%X]\n", cl_ntoh64( port_guid ),
+ min_lid_ho, max_lid_ho );
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ /* the proc returns the fact it sent a set port info */
+ if (__osm_lid_mgr_set_physp_pi( p_mgr, p_physp, cl_hton16( min_lid_ho )))
+ p_mgr->send_set_reqs = TRUE;
+
+ }
+ } /* all ports */
+
+ /* store the guid to lid table in persistant db */
+ osm_db_store( p_mgr->p_g2l );
+
+ if ( p_mgr->send_set_reqs == FALSE )
+ signal = OSM_SIGNAL_DONE;
+ else
+ signal = OSM_SIGNAL_DONE_PENDING;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lft_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_construct(
+ IN osm_lft_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_destroy(
+ IN osm_lft_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_init(
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_lft_rcv_init );
+
+ osm_lft_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_process(
+ IN const osm_lft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_sw_tbl;
+ ib_smp_t *p_smp;
+ uint32_t block_num;
+ osm_switch_t *p_sw;
+ osm_lft_context_t *p_lft_context;
+ uint8_t *p_block;
+ ib_net64_t node_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_block = (uint8_t*)ib_smp_get_payload_ptr( p_smp );
+ block_num = cl_ntoh32( p_smp->attr_mod );
+
+ /*
+ Acquire the switch object for this switch.
+ */
+ p_lft_context = osm_madw_get_lft_context_ptr( p_madw );
+ node_guid = p_lft_context->node_guid;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_process: ERR 0401: "
+ "LFT received for nonexistent node "
+ "0x%" PRIx64 ".\n", cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+ status = osm_switch_set_ft_block( p_sw, p_block, block_num );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_process: ERR 0402: "
+ "Setting forwarding table block failed (%s)"
+ "\n\t\t\t\tSwitch 0x%" PRIx64 ".\n",
+ ib_get_err_str( status ),
+ cl_ntoh64( node_guid ) );
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lft_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lft_rcv_process( ((osm_lft_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_construct(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_destroy(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl,
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lft_rcv_ctrl_init );
+
+ osm_lft_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LFT,
+ __osm_lft_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_ctrl_init: ERR 1601: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lin_fwd_tbl_t.
+ * This object represents an linear forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_lin_fwd_tbl.h>
+
+
+inline size_t
+__osm_lin_tbl_compute_obj_size(
+ IN const uint32_t num_ports )
+{
+ return( sizeof(osm_lin_fwd_tbl_t) + (num_ports - 1) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+ IN uint16_t const size )
+{
+ osm_lin_fwd_tbl_t* p_tbl;
+
+ /*
+ The capacity reported by the switch includes LID 0,
+ so add 1 to the end of the range here for this assert.
+ */
+ CL_ASSERT( size <= IB_LID_UCAST_END_HO + 1 );
+ p_tbl = (osm_lin_fwd_tbl_t*)cl_malloc(
+ __osm_lin_tbl_compute_obj_size( size ) );
+
+ /*
+ Initialize the table to OSM_NO_PATH, which means "invalid port"
+ */
+ cl_memset( p_tbl, OSM_NO_PATH, __osm_lin_tbl_compute_obj_size( size ) );
+ if( p_tbl != NULL )
+ {
+ p_tbl->size = (uint16_t)size;
+ }
+ return( p_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lin_tbl_delete(
+ IN osm_lin_fwd_tbl_t** const pp_tbl )
+{
+ cl_free( *pp_tbl );
+ *pp_tbl = NULL;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_link_mgr_t.
+ * This file implements the Link Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_construct(
+ IN osm_link_mgr_t* const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_destroy(
+ IN osm_link_mgr_t* const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_destroy );
+
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_link_mgr_init(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_link_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_link_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_set_physp_pi(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_physp_t* const p_physp,
+ IN uint8_t const port_state )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_port_info_t* const p_pi = (ib_port_info_t*)payload;
+ const ib_port_info_t* p_old_pi;
+ osm_madw_context_t context;
+ osm_node_t* p_node;
+ ib_api_status_t status;
+ uint8_t port_num;
+ uint8_t mtu;
+ uint8_t op_vls;
+ boolean_t send_set = FALSE;
+ osm_physp_t *p_remote_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_set_physp_pi );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+
+ port_num = osm_physp_get_port_num( p_physp );
+
+ if( port_num == 0 )
+ {
+ osm_switch_t *p_switch;
+ ib_switch_info_t* p_sw_info;
+ /*
+ HCA's don't have a port 0, and for switch port 0,
+ we need to check if this is enhanced port 0 or base port 0.
+ For base port 0 the following parameters are not valid. (p734, table132)
+ */
+ p_switch = osm_get_switch_by_guid( p_mgr->p_subn, p_node->node_info.node_guid );
+ if (! p_switch )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_link_mgr_set_physp_pi: ERR 4201: "
+ "Cannot find switch by guid: 0x%" PRIx64 "\n",
+ cl_ntoh64( p_node->node_info.node_guid ) );
+ goto Exit;
+ }
+
+ p_sw_info = osm_switch_get_si_ptr( p_switch );
+ if (ib_switch_info_is_enhanced_port_0( p_sw_info ) == FALSE)
+ {
+ /* This means the switch doesn't support enhanced port zero.
+ Can skip it. */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_link_mgr_set_physp_pi: "
+ "Skipping port 0, GUID = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ goto Exit;
+ }
+ }
+
+ /*
+ PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
+ */
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ cl_memclr( payload, IB_SMP_DATA_SIZE );
+
+ /* Correction by FUJITSU */
+ cl_memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+
+ /*
+ Correction following a bug injected by the previous
+ FUJITSU line:
+
+ Should never write back a value that is bigger then 3 in
+ the PortPhysicalState field - so can not simply copy!
+
+ Actually we want to write there:
+ port physical state - no change,
+ link down default state = polling
+ port state - no change
+ */
+ p_pi->state_info2 = 0x02;
+ ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+ if ( ib_port_info_get_link_down_def_state(p_pi) !=
+ ib_port_info_get_link_down_def_state(p_old_pi) )
+ send_set = TRUE;
+
+ /* we only change port fields if we do not change state */
+ if (port_state == IB_LINK_NO_CHANGE)
+ {
+ /* The following fields are relevant only for CA port or Enh.SP0 */
+ if( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
+ port_num == 0 )
+ {
+ p_pi->m_key = p_mgr->p_subn->opt.m_key;
+ if (cl_memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
+ send_set = TRUE;
+
+ p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
+ if (cl_memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
+ sizeof(p_pi->subnet_prefix) ))
+ send_set = TRUE;
+
+ p_pi->base_lid = osm_physp_get_base_lid( p_physp );
+ if (cl_memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
+ sizeof(p_pi->base_lid) ))
+ send_set = TRUE;
+
+ /* we are initializing the ports with our local sm_base_lid */
+ p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
+ if (cl_memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
+ sizeof(p_pi->master_sm_base_lid) ))
+ send_set = TRUE;
+
+ p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
+ if (cl_memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period,
+ sizeof(p_pi->m_key_lease_period) ))
+ send_set = TRUE;
+
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ if (cl_memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+ send_set = TRUE;
+
+ ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
+ if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
+ send_set = TRUE;
+ }
+
+ /*
+ Several timeout mechanisms:
+ */
+ p_remote_physp = osm_physp_get_remote( p_physp );
+
+ if (p_remote_physp &&
+ osm_physp_is_valid(p_remote_physp) &&
+ (osm_node_get_type( osm_physp_get_node_ptr(p_remote_physp) ) !=
+ IB_NODE_TYPE_SWITCH))
+ {
+ /* we drive an HCA port so we need to set stall-count to 1 and
+ use leaf hoq value */
+ ib_port_info_set_hoq_lifetime(
+ p_pi, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime);
+ ib_port_info_set_vl_stall_count(
+ p_pi, OSM_DEFAULT_LEAF_VL_STALL_COUNT);
+ }
+ else
+ {
+ ib_port_info_set_hoq_lifetime(
+ p_pi, p_mgr->p_subn->opt.head_of_queue_lifetime);
+ }
+ if ( ib_port_info_get_hoq_lifetime(p_pi) !=
+ ib_port_info_get_hoq_lifetime(p_old_pi) )
+ send_set = TRUE;
+
+ ib_port_info_set_phy_and_overrun_err_thd(
+ p_pi,
+ p_mgr->p_subn->opt.local_phy_errors_threshold,
+ p_mgr->p_subn->opt.overrun_errors_threshold);
+ if (cl_memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold,
+ sizeof(p_pi->error_threshold) ))
+ send_set = TRUE;
+
+ /*
+ Set the easy common parameters for all port types,
+ then determine the neighbor MTU.
+ */
+ p_pi->link_width_enabled = p_old_pi->link_width_supported;
+ if (cl_memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
+ sizeof(p_pi->link_width_enabled) ))
+ send_set = TRUE;
+
+ /* calc new op_vls and mtu */
+ op_vls =
+ osm_physp_calc_link_op_vls(p_mgr->p_log, p_mgr->p_subn, p_physp );
+ mtu = osm_physp_calc_link_mtu(p_mgr->p_log, p_physp );
+
+ ib_port_info_set_neighbor_mtu( p_pi, mtu );
+ if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+ ib_port_info_get_neighbor_mtu(p_old_pi) )
+ send_set = TRUE;
+
+ ib_port_info_set_op_vls( p_pi, op_vls );
+ if ( ib_port_info_get_op_vls(p_pi) !=
+ ib_port_info_get_op_vls(p_old_pi) )
+ send_set = TRUE;
+
+ /* also the context can flag the need to check for errors. */
+ context.pi_context.ignore_errors = FALSE;
+ }
+ else
+ {
+ /*
+ Since the only change we try to do is to modify the port
+ state we can ignore the errors that might becaused by a
+ race in setting the state and the actual state the port is
+ in.
+ */
+ context.pi_context.ignore_errors = FALSE;
+ }
+
+ ib_port_info_set_port_state( p_pi, port_state );
+ if (port_state != IB_LINK_NO_CHANGE &&
+ ib_port_info_get_port_state(p_pi) !=
+ ib_port_info_get_port_state(p_old_pi) )
+ send_set = TRUE;
+
+ context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+ context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+ context.pi_context.set_method = TRUE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ /* We need to send the PortInfoSet request with the new sm_lid
+ in the following cases:
+ 1. There is a change in the values (send_set == TRUE)
+ 2. This is an hca port or a switch port zero and got_set_resp is FALSE
+ (in this case we sent a PortInfoSet in the osm_lid_mgr, but for some reason we
+ didn't get a response) - try and re-send.
+ 3. This is a switch port and:
+ a. first_time_master_sweep flag on the subnet is TRUE. This means the
+ SM just became master, and it then needs to send at PortInfoSet to
+ every port (and this is the first time we can send a PortInfoSet to switch
+ external ports).
+ b. got_set_resp on the physical port is FALSE. This means we haven't seen
+ this port before - need to send PortInfoSet to it.
+ */
+ if (send_set ||
+ (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH && p_physp->got_set_resp == FALSE) ||
+ (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num == 0 &&
+ p_physp->got_set_resp == FALSE) ||
+ (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0 &&
+ (p_mgr->p_subn->first_time_master_sweep == TRUE || p_physp->got_set_resp == FALSE)))
+ {
+ p_mgr->send_set_reqs = TRUE;
+ status = osm_req_set( p_mgr->p_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ payload,
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32(port_num),
+ CL_DISP_MSGID_NONE,
+ &context );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+__osm_link_mgr_process_port(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_port_t* const p_port,
+ IN const uint8_t link_state )
+{
+ uint32_t i;
+ uint32_t num_physp;
+ osm_physp_t *p_physp;
+ uint8_t current_state;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_process_port );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_link_mgr_process_port: "
+ "Port 0x%" PRIx64 " going to %s.\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ ib_get_port_state_str( link_state ) );
+ }
+
+ /*
+ Set the PortInfo for every Physical Port associated
+ with this Port. Start iterating with port 1, since the linkstate
+ is not applicable to the management port on switches.
+ */
+ num_physp = osm_port_get_num_physp( p_port );
+ for( i = 0; i < num_physp; i ++ )
+ {
+ /*
+ Don't bother doing anything if this Physical Port is not valid.
+ or if the state of the port is already better then the
+ specified state.
+ */
+ p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)i );
+ if( p_physp && osm_physp_is_valid( p_physp ) )
+ {
+ current_state = osm_physp_get_port_state( p_physp );
+
+ if( current_state == IB_LINK_DOWN )
+ continue;
+
+ /*
+ Normally we only send state update if state is lower
+ then required state. However, we need to send update if
+ no state change required.
+ */
+ if( (link_state == IB_LINK_NO_CHANGE) ||
+ (current_state < link_state) )
+ {
+ p_mgr->send_set_reqs = FALSE;
+ osm_link_mgr_set_physp_pi(
+ p_mgr,
+ p_physp,
+ link_state );
+
+ if ( p_mgr->send_set_reqs == TRUE )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_link_mgr_process_port: "
+ "Physical port 0x%X already %s. Skipping.\n",
+ osm_physp_get_port_num( p_physp ),
+ ib_get_port_state_str( current_state ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_link_mgr_process(
+ IN osm_link_mgr_t* const p_mgr,
+ IN const uint8_t link_state )
+{
+ cl_qmap_t *p_port_guid_tbl;
+ osm_port_t *p_port;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_process );
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+ p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+ {
+ if( __osm_link_mgr_process_port( p_mgr, p_port, link_state ) ==
+ OSM_SIGNAL_DONE_PENDING )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lid_matrix_t.
+ * This file implements the LID Matrix object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_matrix.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_destroy(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ cl_vector_destroy( &p_lmx->lid_vec );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+cl_status_t
+__osm_lid_matrix_vec_init(
+ IN void* const p_elem,
+ IN void* context )
+{
+ osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+ cl_memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+ return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+void
+__osm_lid_matrix_vec_clear(
+ IN const size_t index,
+ IN void* const p_elem,
+ IN void* context )
+{
+ osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+ UNUSED_PARAM( index );
+ cl_memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_clear(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ cl_vector_apply_func( &p_lmx->lid_vec,
+ __osm_lid_matrix_vec_clear, p_lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_matrix_init(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint8_t num_ports )
+{
+ cl_vector_t *p_vec;
+ cl_status_t status;
+
+ CL_ASSERT( p_lmx );
+ CL_ASSERT( num_ports );
+
+ p_lmx->num_ports = num_ports;
+
+ p_vec = &p_lmx->lid_vec;
+ /*
+ Initialize the vector for the number of ports plus an
+ extra entry to hold the "least-hops" count for that LID.
+ */
+ status = cl_vector_init( p_vec,
+ 0, /* min_size, */
+ 1, /* grow_size */
+ sizeof(uint8_t)*(num_ports + 1), /* element size */
+ __osm_lid_matrix_vec_init, /* init function */
+ NULL, /* destory func */
+ p_lmx /* context */
+ );
+
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+osm_lid_matrix_set(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t val )
+{
+ uint8_t *p_port_array;
+ cl_status_t status;
+
+ CL_ASSERT( port_num < p_lmx->num_ports );
+ status = cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 );
+ if( status == CL_SUCCESS )
+ {
+ p_port_array = (uint8_t *)cl_vector_get_ptr( &p_lmx->lid_vec, lid_ho );
+ p_port_array[port_num] = val;
+ if( p_port_array[p_lmx->num_ports] > val )
+ p_port_array[p_lmx->num_ports] = val;
+ }
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mft_rcv_t.
+ * This object represents the Multicast Forwarding Table Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_construct(
+ IN osm_mft_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_destroy(
+ IN osm_mft_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_init(
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_mft_rcv_init );
+
+ osm_mft_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_process(
+ IN const osm_mft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_sw_tbl;
+ ib_smp_t *p_smp;
+ uint32_t block_num;
+ uint8_t position;
+ osm_switch_t *p_sw;
+ osm_mft_context_t *p_mft_context;
+ uint16_t *p_block;
+ ib_net64_t node_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_block = (uint16_t*)ib_smp_get_payload_ptr( p_smp );
+ block_num = cl_ntoh32( p_smp->attr_mod ) & IB_MCAST_BLOCK_ID_MASK_HO;
+ position = (uint8_t)((cl_ntoh32( p_smp->attr_mod ) &
+ IB_MCAST_POSITION_MASK_HO) >> IB_MCAST_POSITION_SHIFT);
+
+ /*
+ Acquire the switch object for this switch.
+ */
+ p_mft_context = osm_madw_get_mft_context_ptr( p_madw );
+ node_guid = p_mft_context->node_guid;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mft_rcv_process: "
+ "Setting MFT block %u, position %u"
+ "\n\t\t\t\tSwitch 0x%016" PRIx64 ", TID 0x%" PRIx64 ".\n",
+ block_num, position, cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_process: ERR 0801: "
+ "LFT received for nonexistent node "
+ "0x%016" PRIx64 ".\n", cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+ status = osm_switch_set_mft_block( p_sw, p_block,
+ (uint16_t)block_num, position );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_process: ERR 0802: "
+ "Setting forwarding table block failed (%s)"
+ "\n\t\t\t\tSwitch 0x%016" PRIx64
+ ", block_num = %u, position = %u.\n",
+ ib_get_err_str( status ),
+ cl_ntoh64( node_guid ),
+ block_num, position );
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mft_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mft_rcv_process( ((osm_mft_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_construct(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_destroy(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl,
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mft_rcv_ctrl_init );
+
+ osm_mft_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MFT,
+ __osm_mft_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_ctrl_init: ERR 0901: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcast_mgr_t.
+ * This file implements the Multicast Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+typedef struct _osm_mcast_work_obj
+{
+ cl_list_item_t list_item;
+ osm_port_t* p_port;
+
+} osm_mcast_work_obj_t;
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mcast_work_obj_t*
+__osm_mcast_work_obj_new(
+ IN const osm_port_t* const p_port )
+{
+ /*
+ TO DO - get these objects from a lockpool.
+ */
+ osm_mcast_work_obj_t* p_obj;
+
+ /*
+ clean allocated memory to avoid assertion when trying to insert to
+ qlist.
+ see cl_qlist_insert_tail(): CL_ASSERT(p_list_item->p_list != p_list)
+ */
+ p_obj = cl_zalloc( sizeof( *p_obj ) );
+ if( p_obj )
+ p_obj->p_port = (osm_port_t*)p_port;
+
+ return( p_obj );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_work_obj_delete(
+ IN osm_mcast_work_obj_t* p_wobj )
+{
+ cl_free( p_wobj );
+}
+
+/**********************************************************************
+ Recursively remove nodes from the tree
+**********************************************************************/
+void
+__osm_mcast_mgr_purge_tree_node(
+ IN osm_mtree_node_t* p_mtn )
+{
+ uint8_t i;
+
+ for( i = 0; i < p_mtn->max_children; i++ )
+ {
+ if( p_mtn->child_array[i] &&
+ (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+ __osm_mcast_mgr_purge_tree_node( p_mtn->child_array[i] );
+
+ p_mtn->child_array[i] = NULL;
+
+ }
+
+ cl_free( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_tree(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_tree );
+
+ if( p_mgrp->p_root )
+ __osm_mcast_mgr_purge_tree_node( p_mgrp->p_root );
+
+ p_mgrp->p_root = NULL;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint32_t
+osm_mcast_mgr_compute_avg_hops(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw )
+{
+ uint32_t avg_hops = 0;
+ uint32_t hops = 0;
+ uint32_t num_ports = 0;
+ uint16_t base_lid_ho;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_avg_hops );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ For each member of the multicast group, compute the
+ number of hops to its base LID.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_compute_avg_hops: ERR 0A18: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+ hops += osm_switch_get_least_hops( p_sw, base_lid_ho );
+ num_ports++;
+ }
+
+ /*
+ We should be here if there aren't any ports in the group.
+ */
+ CL_ASSERT( num_ports );
+
+ if( num_ports != 0 )
+ {
+ avg_hops = hops / num_ports;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( avg_hops );
+}
+
+/**********************************************************************
+ Calculate the maximal "min hops" from the given switch to any
+ of the group HCAs
+ **********************************************************************/
+uint32_t
+osm_mcast_mgr_compute_max_hops(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw )
+{
+ uint32_t max_hops = 0;
+ uint32_t hops = 0;
+ uint16_t base_lid_ho;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_max_hops );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ For each member of the multicast group, compute the
+ number of hops to its base LID.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get(
+ p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_compute_max_hops: ERR 0A18: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+ hops = osm_switch_get_least_hops( p_sw, base_lid_ho );
+ if (hops > max_hops) max_hops = hops;
+ }
+
+ if( max_hops == 0 )
+ {
+ /*
+ We should be here if there aren't any ports in the group.
+ */
+ max_hops = 10001; /* see later - we use it to realize no hops */
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( max_hops );
+}
+
+/**********************************************************************
+ This function attempts to locate the optimal switch for the
+ center of the spanning tree. The current algorithm chooses
+ a switch with the lowest average hop count to the members
+ of the multicast group.
+**********************************************************************/
+static osm_switch_t*
+__osm_mcast_mgr_find_optimal_switch(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp )
+{
+ cl_qmap_t* p_sw_tbl;
+ const osm_switch_t* p_sw;
+ const osm_switch_t* p_best_sw = NULL;
+ uint32_t hops = 0;
+ uint32_t best_hops = 10000; /* any big # will do */
+ uint64_t sw_guid_ho;
+#ifdef OSM_VENDOR_INTF_ANAFA
+ boolean_t use_avg_hops = TRUE; /* anafa2 - bug hca on switch */ /* use max hops for root */
+#else
+ boolean_t use_avg_hops = FALSE; /* use max hops for root */
+#endif
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_optimal_switch );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ CL_ASSERT( !osm_mgrp_is_empty( p_mgrp ) );
+
+ for( p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+ p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl );
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ) )
+ {
+ if( !osm_switch_supports_mcast( p_sw ) )
+ continue;
+
+ if (use_avg_hops)
+ hops = osm_mcast_mgr_compute_avg_hops( p_mgr, p_mgrp, p_sw );
+ else
+ hops = osm_mcast_mgr_compute_max_hops( p_mgr, p_mgrp, p_sw );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "Switch 0x%016" PRIx64 ", hops = %f.\n",
+ sw_guid_ho, hops );
+ }
+
+ if( hops < best_hops )
+ {
+ p_best_sw = p_sw;
+ best_hops = hops;
+ }
+ }
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ if( p_best_sw )
+ {
+ sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_best_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "Best switch is 0x%" PRIx64 ", hops = %f.\n",
+ sw_guid_ho, best_hops );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "No multicast capable switches detected.\n" );
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( (osm_switch_t*)p_best_sw );
+}
+
+/**********************************************************************
+ This function returns the existing or optimal root swtich for the tree.
+**********************************************************************/
+static osm_switch_t*
+__osm_mcast_mgr_find_root_switch(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp )
+{
+ const osm_switch_t* p_sw = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_root_switch );
+
+ /*
+ We always look for the best multicast tree root switch.
+ Otherwise since we always start with a a single join
+ the root will be always on the first switch attached to it.
+ - Very bad ...
+ */
+ p_sw = __osm_mcast_mgr_find_optimal_switch( p_mgr, p_mgrp );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( (osm_switch_t*)p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_construct(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_destroy(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_destroy );
+
+ CL_ASSERT( p_mgr );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_init(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mcast_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_mcast_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_mcast_mgr_set_tbl(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw )
+{
+ osm_node_t* p_node;
+ osm_dr_path_t* p_path;
+ osm_madw_context_t mad_context;
+ ib_api_status_t status;
+ uint32_t block_id_ho = 0;
+ int16_t block_num = 0;
+ uint32_t position = 0;
+ uint32_t max_position;
+ osm_mcast_tbl_t* p_tbl;
+ ib_net16_t block[IB_MCAST_BLOCK_SIZE];
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_set_tbl );
+
+ CL_ASSERT( p_mgr );
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( p_node );
+
+ p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ CL_ASSERT( p_path );
+
+ /*
+ Send multicast forwarding table blocks to the switch
+ as long as the switch indicates it has blocks needing
+ configuration.
+ */
+
+ mad_context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+ mad_context.mft_context.set_method = TRUE;
+
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+ max_position = p_tbl->max_position;
+
+ while( osm_mcast_tbl_get_block( p_tbl, block_num,
+ (uint8_t)position, block ) )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_set_tbl: "
+ "Writing MFT block 0x%X.\n", block_id_ho );
+ }
+
+ block_id_ho = block_num + (position << 28);
+
+ status = osm_req_set( p_mgr->p_req,
+ p_path,
+ (void*)block,
+ IB_MAD_ATTR_MCAST_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_set_tbl: ERR 0A02: "
+ "Sending linear fwd. tbl. block failed (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ signal = OSM_SIGNAL_DONE_PENDING;
+
+ if( ++position > max_position )
+ {
+ position = 0;
+ block_num++;
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ This is part of the recursive function to compute the paths in the
+ spanning tree that eminate from this switch. On input, the p_list
+ contains the group members that must be routed from this switch.
+**********************************************************************/
+static void
+__osm_mcast_mgr_subdivide(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp,
+ osm_switch_t* const p_sw,
+ cl_qlist_t* const p_list,
+ cl_qlist_t* const list_array,
+ uint8_t const array_size )
+{
+ uint8_t port_num;
+ uint16_t mlid_ho;
+ uint16_t lid_ho;
+ boolean_t ignore_existing;
+ osm_mcast_work_obj_t* p_wobj;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_subdivide );
+
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+ /*
+ For Multicast Groups we want to not count on previous
+ configurations - since we can easily generate a storm
+ by loops.
+ */
+ ignore_existing = TRUE;
+
+ /*
+ Subdivide the set of ports into non-overlapping subsets
+ that will be routed to other switches.
+ */
+ while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list )) !=
+ (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) )
+ {
+ lid_ho = cl_ntoh16( osm_port_get_base_lid( p_wobj->p_port ) );
+
+ port_num = osm_switch_recommend_mcast_path(
+ p_sw, lid_ho, mlid_ho, ignore_existing );
+
+ if( port_num == OSM_NO_PATH )
+ {
+ /*
+ This typically occurs if the switch does not support
+ multicast and the multicast tree must branch at this
+ switch.
+ */
+ uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_subdivide: ERR 0A03: "
+ "Error routing MLID 0x%X through switch 0x%" PRIx64 ".\n"
+ "\t\t\t\tNo multicast paths from this switch for port "
+ "with LID 0x%X.\n",
+ mlid_ho, node_guid_ho, lid_ho );
+
+ __osm_mcast_work_obj_delete( p_wobj );
+ continue;
+ }
+
+ if( port_num > array_size )
+ {
+ uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_subdivide: ERR 0A04: "
+ "Error routing MLID 0x%X through switch "
+ "0x%" PRIx64 ".\n"
+ "\t\t\t\tNo multicast paths from this switch "
+ "to port with LID 0x%X.\n",
+ mlid_ho, node_guid_ho, lid_ho );
+
+ __osm_mcast_work_obj_delete( p_wobj );
+
+ /* This is means OpenSM has a bug. */
+ CL_ASSERT( FALSE );
+ continue;
+ }
+
+ cl_qlist_insert_tail( &list_array[port_num], &p_wobj->list_item );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_list(
+ osm_mcast_mgr_t* const p_mgr,
+ cl_qlist_t* const p_list )
+{
+ osm_mcast_work_obj_t* p_wobj;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_list );
+
+ while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list ) )
+ != (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_purge_list: ERR 0A06: "
+ "Unable to route for port 0x%" PRIx64 ".\n",
+ osm_port_get_guid( p_wobj->p_port ) );
+ __osm_mcast_work_obj_delete( p_wobj );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ This is the recursive function to compute the paths in the spanning
+ tree that eminate from this switch. On input, the p_list contains
+ the group members that must be routed from this switch.
+
+ The function returns the newly created mtree node element.
+**********************************************************************/
+static osm_mtree_node_t*
+__osm_mcast_mgr_branch(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp,
+ osm_switch_t* const p_sw,
+ cl_qlist_t* const p_list,
+ uint8_t depth,
+ uint8_t const upstream_port,
+ uint8_t* const p_max_depth )
+{
+ uint8_t max_children;
+ osm_mtree_node_t* p_mtn = NULL;
+ cl_qlist_t* list_array = NULL;
+ uint8_t i;
+ cl_qmap_t* p_sw_guid_tbl;
+ ib_net64_t node_guid;
+ uint64_t node_guid_ho;
+ osm_mcast_work_obj_t* p_wobj;
+ cl_qlist_t* p_port_list;
+ size_t count;
+ uint16_t mlid_ho;
+ osm_mcast_tbl_t* p_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_branch );
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_list );
+ CL_ASSERT( p_max_depth );
+
+ node_guid = osm_node_get_node_guid( osm_switch_get_node_ptr( p_sw ) );
+ node_guid_ho = cl_ntoh64( node_guid );
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_branch: "
+ "Routing MLID 0x%X through switch 0x%" PRIx64 ".\n"
+ "\t\t\t\t%u nodes at depth %u.\n",
+ mlid_ho,
+ node_guid_ho,
+ cl_qlist_count( p_list ), depth );
+ }
+
+ CL_ASSERT( cl_qlist_count( p_list ) > 0 );
+
+ depth++;
+
+ if( depth > *p_max_depth )
+ {
+ CL_ASSERT( depth == *p_max_depth + 1 );
+ *p_max_depth = depth;
+ }
+
+ if( osm_switch_supports_mcast( p_sw ) == FALSE )
+ {
+ /*
+ This switch doesn't do multicast. Clean-up.
+ */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A14: "
+ "Switch 0x%" PRIx64 " does not support multicast.\n",
+ node_guid_ho );
+
+ /*
+ Deallocate all the work objects on this branch of the tree.
+ */
+ __osm_mcast_mgr_purge_list( p_mgr, p_list );
+ goto Exit;
+ }
+
+ p_mtn = osm_mtree_node_new( p_sw );
+ if( p_mtn == NULL )
+ {
+ /*
+ We are unable to continue routing down this
+ leg of the tree. Clean-up.
+ */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A15: "
+ "Insufficient memory to build multicast tree.\n" );
+
+ /*
+ Deallocate all the work objects on this branch of the tree.
+ */
+ __osm_mcast_mgr_purge_list( p_mgr, p_list );
+ goto Exit;
+ }
+
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ max_children = osm_mtree_node_get_max_children( p_mtn );
+
+ CL_ASSERT( max_children > 1 );
+
+ /*
+ Prepare an empty list for each port in the switch.
+ TO DO - this list array could probably be moved
+ inside the switch element to save on malloc thrashing.
+ */
+ list_array = cl_zalloc( sizeof(cl_qlist_t) * max_children );
+ if( list_array == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A16: "
+ "Unable to allocate list array.\n" );
+ __osm_mcast_mgr_purge_list( p_mgr, p_list );
+ goto Exit;
+ }
+
+ for( i = 0; i < max_children; i++ )
+ cl_qlist_init( &list_array[i] );
+
+ __osm_mcast_mgr_subdivide( p_mgr, p_mgrp, p_sw, p_list, list_array,
+ max_children );
+
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+ /*
+ Add the upstream port to the forwarding table unless
+ we're at the root of the spanning tree.
+ */
+ if( depth > 1 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Adding upstream port 0x%X.\n", upstream_port );
+ }
+
+ CL_ASSERT( upstream_port );
+ osm_mcast_tbl_set( p_tbl, mlid_ho, upstream_port );
+ }
+
+ /*
+ For each port that was allocated some routes,
+ recurse into this function to continue building the tree
+ if the node on the other end of that port is another switch.
+ Otherwise, the node is an endpoint, and we've found a leaf
+ of the tree. Mark leaves with our special pointer value.
+ */
+
+ for( i = 0; i < max_children; i++ )
+ {
+ const osm_physp_t *p_physp;
+ const osm_physp_t *p_remote_physp;
+ const osm_node_t *p_node;
+ const osm_node_t *p_remote_node;
+ osm_switch_t *p_remote_sw;
+
+ p_port_list = &list_array[i];
+
+ count = cl_qlist_count( p_port_list );
+
+ /*
+ There should be no children routed through the upstream port!
+ */
+ CL_ASSERT( ( upstream_port == 0 ) || ( i != upstream_port) ||
+ ( (i == upstream_port) && (count == 0)) );
+
+ if( count == 0)
+ continue; /* No routes down this port. */
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Routing %u destination(s) via switch port 0x%X.\n",
+ count, i );
+ }
+
+ /*
+ This port routes frames for this mcast group. Therefore,
+ set the appropriate bit in the multicast forwarding
+ table for this switch.
+ */
+ osm_mcast_tbl_set( p_tbl, mlid_ho, i );
+ if (i == 0)
+ /* This means we are adding the switch to the mc group.
+ We do not need to continue looking at the remote port, just
+ needed to add the port to the table */
+ continue;
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_remote_node = osm_node_get_remote_node( p_node, i, NULL );
+
+ if( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH )
+ {
+ /*
+ Acquire a pointer to the remote switch then recurse.
+ */
+ p_remote_sw = (osm_switch_t*)cl_qmap_get(
+ p_sw_guid_tbl, osm_node_get_node_guid( p_remote_node ) );
+ CL_ASSERT( p_remote_sw );
+
+ p_physp = osm_node_get_physp_ptr( p_node, i );
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ CL_ASSERT( p_remote_physp );
+ CL_ASSERT( osm_physp_is_valid( p_remote_physp ) );
+
+ p_mtn->child_array[i] = __osm_mcast_mgr_branch(
+ p_mgr, p_mgrp, p_remote_sw,
+ p_port_list, depth,
+ osm_physp_get_port_num( p_remote_physp),
+ p_max_depth );
+ }
+ else
+ {
+ /*
+ The neighbor node is not a switch, so this
+ must be a leaf.
+ */
+ CL_ASSERT( count == 1 );
+
+ p_mtn->child_array[i] = OSM_MTREE_LEAF;
+ p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head(
+ p_port_list );
+
+ CL_ASSERT( cl_is_qlist_empty( p_port_list ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Found leaf for port 0x%016" PRIx64 ",\n"
+ "\t\t\t\ton switch port 0x%X.\n",
+ cl_ntoh64( osm_port_get_guid( p_wobj->p_port ) ), i );
+ }
+
+ __osm_mcast_work_obj_delete( p_wobj );
+ }
+ }
+
+ cl_free( list_array );
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mcast_mgr_build_spanning_tree(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp )
+{
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ uint32_t num_ports;
+ cl_qlist_t port_list;
+ osm_switch_t* p_sw;
+ osm_mcast_work_obj_t* p_wobj;
+ ib_api_status_t status = IB_SUCCESS;
+ uint8_t max_depth = 0;
+ uint32_t count;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_build_spanning_tree );
+
+ cl_qlist_init( &port_list );
+
+ /*
+ TO DO - for now, just blow away the old tree.
+ In the future we'll need to construct the tree based
+ on multicast forwarding table information if the user wants to
+ preserve existing multicast routes.
+ */
+ __osm_mcast_mgr_purge_tree( p_mgr, p_mgrp );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ num_ports = cl_qmap_count( p_mcm_tbl );
+ if( num_ports == 0 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_build_spanning_tree: "
+ "MLID 0x%X has no members--nothing to do.\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+ }
+ goto Exit;
+ }
+
+ /*
+ This function builds the single spanning tree recursively.
+ At each stage, the ports to be reached are divided into
+ non-overlapping subsets of member ports that can be reached through
+ a given switch port. Construction then moves down each
+ branch, and the process starts again with each branch computing
+ for its own subset of the member ports.
+
+ The maximum recursion depth is at worst the maximum hop count in the
+ subnet, which is spec limited to 64.
+ */
+
+ /*
+ Locate the switch around which to create the spanning
+ tree for this multicast group.
+ */
+ p_sw = __osm_mcast_mgr_find_root_switch( p_mgr, p_mgrp );
+ if( p_sw == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A08: "
+ "Unable to locate a suitable switch for group 0x%X.\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ));
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ Build the first "subset" containing all member ports.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A09: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ p_wobj = __osm_mcast_work_obj_new( p_port );
+ if( p_wobj == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A10: "
+ "Insufficient memory to route port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ continue;
+ }
+
+ cl_qlist_insert_tail( &port_list, &p_wobj->list_item );
+ }
+
+ count = cl_qlist_count( &port_list );
+ p_mgrp->p_root = __osm_mcast_mgr_branch( p_mgr, p_mgrp, p_sw,
+ &port_list, 0, 0, &max_depth );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_build_spanning_tree: "
+ "Configured MLID 0x%X for %u ports, max tree depth = %u.\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ),
+ count, max_depth );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+#if 0
+/* unused */
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_set_table(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const osm_mtree_node_t* const p_mtn )
+{
+ uint8_t i;
+ uint8_t max_children;
+ osm_mtree_node_t* p_child_mtn;
+ uint16_t mlid_ho;
+ osm_mcast_tbl_t* p_tbl;
+ osm_switch_t* p_sw;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_set_table );
+
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+ p_sw = osm_mtree_node_get_switch_ptr( p_mtn );
+
+ CL_ASSERT( p_sw );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_mcast_mgr_set_table: "
+ "Configuring MLID 0x%X on switch 0x%" PRIx64 ".\n",
+ mlid_ho, osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+ }
+
+ /*
+ For every child of this tree node, set the corresponding
+ bit in the switch's mcast table.
+ */
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+ max_children = osm_mtree_node_get_max_children( p_mtn );
+
+ CL_ASSERT( max_children <= osm_switch_get_num_ports( p_sw ) );
+
+ osm_mcast_tbl_clear_mlid( p_tbl, mlid_ho );
+
+ for( i = 0; i < max_children; i++ )
+ {
+ p_child_mtn = osm_mtree_node_get_child( p_mtn, i );
+ if( p_child_mtn == NULL )
+ continue;
+
+ osm_mcast_tbl_set( p_tbl, mlid_ho, i );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_clear(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp )
+{
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_tbl;
+ osm_mcast_tbl_t* p_mcast_tbl;
+
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_clear );
+
+ /*
+ Walk the switches and clear the routing entries for
+ this MLID.
+ */
+ p_tbl = &p_mgr->p_subn->sw_guid_tbl;
+ p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+ while( p_sw != (osm_switch_t*)cl_qmap_end( p_tbl ) )
+ {
+ p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+ osm_mcast_tbl_clear_mlid( p_mcast_tbl, cl_ntoh16(p_mgrp->mlid) );
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+#if 0
+/* TO DO - make this real -- at least update spanning tree */
+/**********************************************************************
+ Lock must be held on entry.
+**********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_process_single(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN ib_net16_t const mlid,
+ IN ib_net64_t const port_guid,
+ IN uint8_t const join_state )
+{
+ uint8_t port_num;
+ uint16_t mlid_ho;
+ osm_switch_t* p_sw;
+ ib_net64_t sw_guid;
+ osm_port_t* p_port;
+ osm_physp_t* p_physp;
+ osm_physp_t* p_remote_physp;
+ osm_node_t* p_remote_node;
+ cl_qmap_t* p_port_tbl;
+ cl_qmap_t* p_sw_tbl;
+ osm_mcast_tbl_t* p_mcast_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_single );
+
+ CL_ASSERT( mlid );
+ CL_ASSERT( port_guid );
+
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+ mlid_ho = cl_ntoh16( mlid );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "Attempting to add port 0x%" PRIx64 " to MLID 0x%X, "
+ "\n\t\t\t\tjoin state = 0x%X.\n",
+ cl_ntoh64( port_guid ), mlid_ho, join_state );
+ }
+
+ /*
+ Acquire the Port object.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A01: "
+ "Unable to acquire port object for 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ if( p_physp == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A05: "
+ "Unable to acquire phsyical port object for 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A07: "
+ "Unable to acquire valid physical port object "
+ "for 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A11: "
+ "Unable to acquire remote phsyical port object "
+ "for 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( !osm_physp_is_valid( p_remote_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A21: "
+ "Unable to acquire valid remote physical port object "
+ "for 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+
+ CL_ASSERT( p_remote_node );
+
+ sw_guid = osm_node_get_node_guid( p_remote_node );
+
+ if( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A22: "
+ "Remote node not a switch node 0x%" PRIx64 ".\n",
+ cl_ntoh64( sw_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_tbl, sw_guid );
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A12: "
+ "No switch object 0x%" PRIx64 ".\n",
+ cl_ntoh64( sw_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( osm_switch_is_in_mcast_tree( p_sw, mlid_ho ) )
+ {
+ /*
+ We're in luck. The switch attached to this port
+ is already in the multicast group, so we can just
+ add the specified port as a new leaf of the tree.
+ */
+ if( join_state & (IB_JOIN_STATE_FULL | IB_JOIN_STATE_NON ) )
+ {
+ /*
+ This node wants to receive multicast frames.
+ Get the switch port number to which the new member port
+ is attached, then configure this single mcast table.
+ */
+ port_num = osm_physp_get_port_num( p_remote_physp );
+ CL_ASSERT( port_num );
+
+ p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+ osm_mcast_tbl_set( p_mcast_tbl, mlid_ho, port_num );
+ }
+ else
+ {
+ if( join_state & IB_JOIN_STATE_SEND_ONLY )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "Success. Nothing to do for send"
+ "only member.\n" );
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A13: "
+ "Unknown join state 0x%X.\n", join_state );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "Unable to add port.\n" );
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+#endif
+
+/**********************************************************************
+ lock must already be held on entry
+**********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_process_tree(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp,
+ IN osm_mcast_req_type_t req_type,
+ ib_net64_t port_guid )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ cl_qmap_t* p_tbl;
+ ib_net16_t mlid;
+ boolean_t ui_mcast_fdb_assign_func_defined;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_tree );
+
+ mlid = osm_mgrp_get_mlid( p_mgrp );
+ p_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "Processing multicast group 0x%X.\n", cl_ntoh16( mlid ));
+ }
+
+ /*
+ If there are no switches in the subnet, then we have nothing to do.
+ */
+ if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) == 0 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "No switches in subnet. Nothing to do.\n" );
+ }
+ goto Exit;
+ }
+
+ if (p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign)
+ ui_mcast_fdb_assign_func_defined = TRUE;
+ else
+ ui_mcast_fdb_assign_func_defined = FALSE;
+
+ /*
+ Clear the multicast tables to start clean, then build
+ the spanning tree which sets the mcast table bits for each
+ port in the group.
+ We will clean the multicast tables if a ui_mcast function isn't
+ defined, or if such function is defined, but we got here
+ through a MC_CREATE request - this means we are creating a new
+ multicast group - clean all old data.
+ */
+ if ( ui_mcast_fdb_assign_func_defined == FALSE ||
+ req_type == OSM_MCAST_REQ_TYPE_CREATE )
+ __osm_mcast_mgr_clear( p_mgr, p_mgrp );
+
+ /* If a UI function is defined, then we will call it here.
+ If not - the use the regular build spanning tree function */
+ if ( ui_mcast_fdb_assign_func_defined == FALSE )
+ {
+ status = __osm_mcast_mgr_build_spanning_tree( p_mgr, p_mgrp );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_tree: ERR 0A17: "
+ "Unable to create spanning tree (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "Invoking UI function pfn_ui_mcast_fdb_assign\n");
+ }
+
+ p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign(
+ p_mgr->p_subn->opt.ui_mcast_fdb_assign_ctx,
+ mlid, req_type, port_guid );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_dump_mcast_routes(
+ IN const osm_mcast_mgr_t* const p_mgr,
+ IN const osm_switch_t* const p_sw )
+{
+ osm_mcast_tbl_t* p_tbl;
+ int16_t mlid_ho = 0;
+ int16_t mlid_start_ho;
+ uint8_t position = 0;
+ int16_t block_num = 0;
+ char line[OSM_REPORT_LINE_SIZE];
+ boolean_t print_lid;
+ const osm_node_t* p_node;
+ FILE * p_mcfdbFile;
+ uint16_t i, j;
+ uint16_t mask_entry;
+ char *file_name = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_dump_mcast_routes );
+
+ if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ goto Exit;
+
+ file_name =
+ (char*)cl_malloc(strlen(p_mgr->p_subn->opt.dump_files_dir) + 12);
+
+ CL_ASSERT(file_name);
+
+ strcpy(file_name, p_mgr->p_subn->opt.dump_files_dir);
+ strcat(file_name,"/osm.mcfdbs");
+
+ /* Open the file or error */
+ p_mcfdbFile = fopen(file_name, "a");
+ if (! p_mcfdbFile)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_dump_mcast_routes: ERR 0A23: "
+ "Fail to open mcfdb file (%s).\n",
+ file_name );
+ goto Exit;
+ }
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+ fprintf( p_mcfdbFile, "\nSwitch 0x%016" PRIx64 "\n"
+ "LID : Out Port(s) \n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ while ( block_num <= p_tbl->max_block_in_use )
+ {
+ mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+ for (i = 0 ; i < IB_MCAST_BLOCK_SIZE ; i++)
+ {
+ mlid_ho = mlid_start_ho + i;
+ position = 0;
+ print_lid = FALSE;
+ sprintf( line, "0x%04X :", mlid_ho + IB_LID_MCAST_START_HO );
+ while ( position <= p_tbl->max_position )
+ {
+ mask_entry = cl_ntoh16((*p_tbl->p_mask_tbl)[mlid_ho][position]);
+ if (mask_entry == 0)
+ {
+ position++;
+ continue;
+ }
+ print_lid = TRUE;
+ for (j = 0 ; j < 16 ; j++)
+ {
+ if ( (1 << j) & mask_entry )
+ sprintf( line, "%s 0x%03X ", line, j+(position*16) );
+ }
+ position++;
+ }
+ if (print_lid)
+ {
+ fprintf( p_mcfdbFile, "%s\n", line );
+ }
+ }
+ block_num++;
+ }
+
+ fclose(p_mcfdbFile);
+
+ Exit:
+ if (file_name)
+ cl_free(file_name);
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Process the entire group.
+
+ NOTE : The lock should be held externally!
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process_mgrp(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp,
+ IN osm_mcast_req_type_t req_type,
+ IN ib_net64_t port_guid )
+{
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+ ib_api_status_t status;
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_tbl;
+ boolean_t pending_transactions = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp );
+
+ p_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp, req_type, port_guid );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_mgrp: ERR 0A19: "
+ "Unable to create spanning tree (%s).\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ /* initialize the mc fdb dump file: */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ unlink("/tmp/osm.mcfdbs");
+
+ /*
+ Walk the switches and download the tables for each.
+ */
+ p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+ while( p_sw != (osm_switch_t*)cl_qmap_end( p_tbl ) )
+ {
+ signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+ if( signal == OSM_SIGNAL_DONE_PENDING )
+ pending_transactions = TRUE;
+
+ osm_mcast_mgr_dump_mcast_routes( p_mgr, p_sw );
+
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ if( pending_transactions == TRUE )
+ return( OSM_SIGNAL_DONE_PENDING );
+ else
+ return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ osm_signal_t signal;
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_tbl;
+ cl_qmap_t* p_mcast_tbl;
+ osm_mgrp_t* p_mgrp;
+ ib_api_status_t status;
+ boolean_t pending_transactions = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process );
+
+ p_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ p_mcast_tbl = &p_mgr->p_subn->mgrp_mlid_tbl;
+ /*
+ While holding the lock, iterate over all the established
+ multicast groups, servicing each in turn.
+
+ Then, download the multicast tables to the switches.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ p_mgrp = (osm_mgrp_t*)cl_qmap_head( p_mcast_tbl );
+ while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( p_mcast_tbl ) )
+ {
+ /* We reached here due to some change that caused a heavy sweep
+ of the subnet. Not due to a specific multicast request.
+ So the request type is subnet_change and the port guid is 0. */
+ status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp,
+ OSM_MCAST_REQ_TYPE_SUBNET_CHANGE, 0);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process: ERR 0A20: "
+ "Unable to create spanning tree (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ /* initialize the mc fdb dump file: */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ unlink("/tmp/osm.mcfdbs");
+
+ /*
+ Walk the switches and download the tables for each.
+ */
+ p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+ while( p_sw != (osm_switch_t*)cl_qmap_end( p_tbl ) )
+ {
+ signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+ if( signal == OSM_SIGNAL_DONE_PENDING )
+ pending_transactions = TRUE;
+
+ osm_mcast_mgr_dump_mcast_routes( p_mgr, p_sw );
+
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ if( pending_transactions == TRUE )
+ return( OSM_SIGNAL_DONE_PENDING );
+ else
+ return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN ib_net16_t const mlid)
+{
+ cl_map_item_t *map_item;
+
+ map_item = cl_qmap_get(&p_mgr->p_subn->mgrp_mlid_tbl, mlid);
+ if(map_item == cl_qmap_end(&p_mgr->p_subn->mgrp_mlid_tbl))
+ {
+ return NULL;
+ }
+ return (osm_mgrp_t *)map_item;
+}
+
+/**********************************************************************
+ This is the function that is invoked during idle time to handle the
+ process request. Context1 is simply the osm_mcast_mgr_t*, Context2
+ hold the mlid, port guid and action (join/leave/delete) required.
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+ IN void* const Context1,
+ IN void* const Context2 )
+{
+ osm_mcast_mgr_t* p_mgr = (osm_mcast_mgr_t*)Context1;
+ osm_mgrp_t* p_mgrp;
+ ib_net16_t mlid;
+ osm_signal_t signal;
+ osm_mcast_mgr_ctxt_t* p_ctxt = (osm_mcast_mgr_ctxt_t*)Context2;
+ osm_mcast_req_type_t req_type = p_ctxt->req_type;
+ ib_net64_t port_guid = p_ctxt->port_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp_cb );
+
+ /* nice copy no warning on size diff */
+ cl_memcpy(&mlid, &p_ctxt->mlid, sizeof(mlid));
+
+ /* we can destroy the context now */
+ cl_free(p_ctxt);
+
+ /* we need a lock to make sure the p_mgrp is not change other ways */
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+ p_mgrp = __get_mgrp_by_mlid( p_mgr, mlid);
+
+ /* since we delayed the execution we prefer to pass the
+ mlid as the mgrp identifier and then find it or abort */
+
+ if (p_mgrp)
+ {
+
+ /* if there was no change from the last time we processed the group
+ we can skip doing anything
+ */
+ if ( p_mgrp->last_change_id == p_mgrp->last_tree_id)
+ {
+ signal = OSM_SIGNAL_DONE;
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Skip processing mgrp with lid:0x%X change id:%u \n",
+ cl_ntoh16(mlid), p_mgrp->last_change_id );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Processing mgrp with lid:0x%X change id:%u \n",
+ cl_ntoh16(mlid), p_mgrp->last_change_id );
+
+ signal =
+ osm_mcast_mgr_process_mgrp( p_mgr, p_mgrp, req_type, port_guid );
+ p_mgrp->last_tree_id = p_mgrp->last_change_id;
+ }
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ /* Remove MGRP only if osm_mcm_port_t count is 0 and
+ * Not a well known group
+ */
+ if((0x0 == cl_qmap_count(&p_mgrp->mcm_port_tbl)) &&
+ (p_mgrp->well_known == FALSE))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Destroying mgrp with lid:0x%X \n",
+ cl_ntoh16(mlid) );
+
+ /* Send a Report to any InformInfo registerd for
+ Trap 67 : MCGroup delete */
+ osm_mgrp_send_delete_notice( p_mgr->p_subn, p_mgr->p_log, p_mgrp );
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+ cl_qmap_remove_item(&p_mgr->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_mgrp );
+
+ osm_mgrp_destroy(p_mgrp);
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ }
+ /* no need for CL_PLOCK_RELEASE( p_mgr->p_lock ) - internally done */
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return signal;
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return OSM_SIGNAL_DONE;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcast_tbl_t.
+ * This object represents an multicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_mcast_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_tbl_init(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN uint8_t const num_ports,
+ IN uint16_t const capacity )
+{
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( num_ports );
+
+ cl_memclr( p_tbl, sizeof(*p_tbl) );
+
+ p_tbl->max_block_in_use = -1;
+
+ if( capacity == 0 )
+ {
+ /*
+ This switch apparently doesn't support multicast.
+ Everything is initialized to zero already, so return.
+ */
+ return( IB_SUCCESS );
+ }
+
+ p_tbl->num_entries = capacity;
+ p_tbl->num_ports = num_ports;
+ p_tbl->max_position = (uint8_t)((ROUNDUP( num_ports, IB_MCAST_MASK_SIZE) /
+ IB_MCAST_MASK_SIZE) - 1);
+
+ p_tbl->max_block = (uint16_t)((ROUNDUP( p_tbl->num_entries,
+ IB_MCAST_BLOCK_SIZE ) / IB_MCAST_BLOCK_SIZE) - 1);
+
+ p_tbl->max_mlid_ho = (uint16_t)(IB_LID_MCAST_START_HO + capacity);
+
+ /*
+ The number of bytes needed in the mask table is:
+ The (maximum bit mask 'position' + 1) times the
+ number of bytes in each bit mask times the
+ number of MLIDs supported by the table.
+
+ We must always allocate the array with the maximum position
+ since it is (and must be) defined that way the table structure
+ in order to create a pointer to a two dimensional array.
+ */
+ p_tbl->p_mask_tbl = cl_zalloc( p_tbl->num_entries *
+ (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 );
+
+ if( p_tbl->p_mask_tbl == NULL )
+ return( IB_INSUFFICIENT_MEMORY );
+
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_destroy(
+ IN osm_mcast_tbl_t* const p_tbl )
+{
+ cl_free( p_tbl->p_mask_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_set(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port )
+{
+ uintn_t mlid_offset;
+ uintn_t mask_offset;
+ uintn_t bit_mask;
+ int16_t block_num;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+ CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+ CL_ASSERT( p_tbl->p_mask_tbl );
+
+ mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+ mask_offset = port / IB_MCAST_MASK_SIZE;
+ bit_mask = cl_ntoh16( (uint16_t)( 1 << (port % IB_MCAST_MASK_SIZE) ) );
+ (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask;
+
+ block_num = (int16_t)(mlid_offset / IB_MCAST_BLOCK_SIZE);
+
+ if( block_num > p_tbl->max_block_in_use )
+ p_tbl->max_block_in_use = (uint16_t)block_num;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_is_port(
+ IN const osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port_num )
+{
+ uintn_t mlid_offset;
+ uintn_t mask_offset;
+ uintn_t bit_mask;
+
+ CL_ASSERT( p_tbl );
+
+ if( p_tbl->p_mask_tbl )
+ {
+ CL_ASSERT( port_num <= (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+ CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+
+ mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+ mask_offset = port_num / IB_MCAST_MASK_SIZE;
+ bit_mask = cl_ntoh16(
+ (uint16_t)( 1 << (port_num % IB_MCAST_MASK_SIZE) ) );
+ return( ((*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) ==
+ bit_mask );
+ }
+
+ return( FALSE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_is_any_port(
+ IN const osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho )
+{
+ uintn_t mlid_offset;
+ uint8_t position;
+ uint16_t result = 0;
+
+ CL_ASSERT( p_tbl );
+
+ if( p_tbl->p_mask_tbl )
+ {
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+ CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+
+ mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+
+ for( position = 0; position <= p_tbl->max_position; position++ )
+ result |= (*p_tbl->p_mask_tbl)[mlid_offset][position];
+ }
+
+ return( result != 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_tbl_set_block(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const ib_net16_t* const p_block,
+ IN const int16_t block_num,
+ IN const uint8_t position )
+{
+ uint32_t i;
+ uint16_t mlid_start_ho;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( p_block );
+
+ if( block_num > p_tbl->max_block )
+ return( IB_INVALID_PARAMETER );
+
+ if( position > p_tbl->max_position )
+ return( IB_INVALID_PARAMETER );
+
+ mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+
+ if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho )
+ return( IB_INVALID_PARAMETER );
+
+ for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ )
+ (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i];
+
+ if( block_num > p_tbl->max_block_in_use )
+ p_tbl->max_block_in_use = (uint16_t)block_num;
+
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_clear_mlid(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho )
+{
+ uint8_t i;
+ uintn_t mlid_offset;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+
+ if( p_tbl->p_mask_tbl && (mlid_ho <= p_tbl->max_mlid_ho) )
+ {
+ mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+ for( i = 0; i <= p_tbl->max_position; i++ )
+ (*p_tbl->p_mask_tbl)[mlid_offset][i] = 0;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_get_block(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN int16_t const block_num,
+ IN uint8_t const position,
+ OUT ib_net16_t* const p_block )
+{
+ uint32_t i;
+ uint16_t mlid_start_ho;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( p_block );
+
+ if( block_num > p_tbl->max_block_in_use )
+ return( FALSE );
+
+ if( position > p_tbl->max_position )
+ {
+ /*
+ Caller shouldn't do this for efficiency's sake...
+ */
+ cl_memclr( p_block, IB_SMP_DATA_SIZE );
+ return( TRUE );
+ }
+
+ mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+
+ if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho )
+ return( IB_INVALID_PARAMETER );
+
+ for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ )
+ p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
+
+ return( TRUE );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_mcm_info.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_destroy(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ CL_ASSERT( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_init(
+ IN osm_mcm_info_t* const p_mcm,
+ IN const ib_net16_t mlid )
+{
+ CL_ASSERT( p_mcm );
+ p_mcm->mlid = mlid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_info_t*
+osm_mcm_info_new(
+ IN const ib_net16_t mlid )
+{
+ osm_mcm_info_t* p_mcm;
+
+ p_mcm = (osm_mcm_info_t*)cl_zalloc( sizeof(*p_mcm) );
+ if( p_mcm )
+ {
+ osm_mcm_info_init( p_mcm, mlid );
+ }
+
+ return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_delete(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ osm_mcm_info_destroy( p_mcm );
+ cl_free( p_mcm );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcm_port_t.
+ * This object represents the membership of a port in a multicast group.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_mcm_port.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_construct(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ cl_memclr( p_mcm, sizeof(*p_mcm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_destroy(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ /*
+ Nothing to do?
+ */
+ UNUSED_PARAM( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_init(
+ IN osm_mcm_port_t* const p_mcm,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join )
+{
+ CL_ASSERT( p_mcm );
+ CL_ASSERT( p_port_gid );
+ CL_ASSERT( scope_state );
+
+ osm_mcm_port_construct( p_mcm );
+ p_mcm->port_gid = *p_port_gid;
+ p_mcm->scope_state = scope_state;
+ p_mcm->proxy_join = proxy_join;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mcm_port_new(
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join )
+{
+ osm_mcm_port_t* p_mcm;
+
+ p_mcm = cl_malloc( sizeof(*p_mcm) );
+ if( p_mcm )
+ {
+ osm_mcm_port_init( p_mcm, p_port_gid,
+ scope_state, proxy_join );
+ }
+
+ return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_delete(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ CL_ASSERT( p_mcm );
+
+ osm_mcm_port_destroy( p_mcm );
+ cl_free( p_mcm );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mtree_node_t.
+ * This file implements the Multicast Tree object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_mtree.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_node_init(
+ IN osm_mtree_node_t* const p_mtn,
+ IN const osm_switch_t* const p_sw )
+{
+ uint32_t i;
+
+ CL_ASSERT( p_mtn );
+ CL_ASSERT( p_sw );
+
+ osm_mtree_node_construct( p_mtn );
+
+ p_mtn->p_sw = (osm_switch_t*)p_sw;
+ p_mtn->max_children = osm_switch_get_num_ports( p_sw );
+
+ for( i = 0; i < p_mtn->max_children; i++ )
+ p_mtn->child_array[i] = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mtree_node_t*
+osm_mtree_node_new(
+ IN const osm_switch_t* const p_sw )
+{
+ osm_mtree_node_t *p_mtn;
+
+ p_mtn = cl_malloc( sizeof(osm_mtree_node_t) +
+ sizeof(void*) * (osm_switch_get_num_ports( p_sw ) - 1) );
+
+ if( p_mtn != NULL )
+ osm_mtree_node_init( p_mtn, p_sw );
+
+ return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_destroy(
+ IN osm_mtree_node_t *p_mtn )
+{
+ uint32_t i;
+
+ if (p_mtn == NULL) return;
+
+ if ( p_mtn->child_array != NULL )
+ for (i = 0 ; i< p_mtn->max_children; i++ )
+ if ( (p_mtn->child_array[i] != NULL) &&
+ (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+ osm_mtree_destroy(p_mtn->child_array[i]);
+
+ cl_free( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mtree_dump(
+ IN osm_mtree_node_t *p_mtn )
+{
+ uint32_t i;
+
+ if (p_mtn == NULL) return;
+
+ printf("GUID:0x%016" PRIx64 " max_children:%d\n",
+ p_mtn->p_sw->p_node->node_info.node_guid,
+ p_mtn->max_children );
+ if ( p_mtn->child_array != NULL )
+ {
+ for (i = 0 ; i< p_mtn->max_children; i++ )
+ {
+ printf("i=%d\n", i);
+ if ( (p_mtn->child_array[i] != NULL) && (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+ __osm_mtree_dump(p_mtn->child_array[i]);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of multicast functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+/* osm_mcast_req_type_t values converted to test for easier printing. */
+const char* osm_mcast_req_type_str[] =
+{
+ "OSM_MCAST_REQ_TYPE_CREATE",
+ "OSM_MCAST_REQ_TYPE_JOIN",
+ "OSM_MCAST_REQ_TYPE_LEAVE",
+ "OSM_MCAST_REQ_TYPE_SUBNET_CHANGE"
+};
+
+const char*
+osm_get_mcast_req_type_str(
+ IN osm_mcast_req_type_t req_type )
+{
+ if ( req_type > OSM_MCAST_REQ_TYPE_SUBNET_CHANGE )
+ req_type = OSM_MCAST_REQ_TYPE_SUBNET_CHANGE;
+ return( osm_mcast_req_type_str[req_type] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_construct(
+ IN osm_mgrp_t* const p_mgrp )
+{
+ cl_memclr( p_mgrp, sizeof(*p_mgrp) );
+ cl_qmap_init( &p_mgrp->mcm_port_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_destroy(
+ IN osm_mgrp_t* const p_mgrp )
+{
+ osm_mcm_port_t *p_mcm_port;
+ osm_mcm_port_t *p_next_mcm_port;
+
+ CL_ASSERT(p_mgrp);
+
+ p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_head( &p_mgrp->mcm_port_tbl );
+ while( p_next_mcm_port != (osm_mcm_port_t*)cl_qmap_end( &p_mgrp->mcm_port_tbl ) )
+ {
+ p_mcm_port = p_next_mcm_port;
+ p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_next( &p_mcm_port->map_item );
+ osm_mcm_port_delete( p_mcm_port );
+ }
+ /* destroy the mtree_node structure */
+ osm_mtree_destroy(p_mgrp->p_root);
+
+ cl_free(p_mgrp);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_init(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net16_t mlid )
+{
+ CL_ASSERT( p_mgrp );
+ CL_ASSERT( cl_ntoh16( mlid ) >= IB_LID_MCAST_START_HO );
+
+ osm_mgrp_construct( p_mgrp );
+ p_mgrp->mlid = mlid;
+ p_mgrp->last_change_id = 0;
+ p_mgrp->last_tree_id = 0;
+ p_mgrp->to_be_deleted = FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mgrp_t*
+osm_mgrp_new(
+ IN const ib_net16_t mlid )
+{
+ osm_mgrp_t* p_mgrp;
+
+ p_mgrp = (osm_mgrp_t*)cl_malloc( sizeof(*p_mgrp) );
+ if( p_mgrp )
+ osm_mgrp_init( p_mgrp, mlid );
+
+ return( p_mgrp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mgrp_add_port(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t join_state,
+ IN boolean_t proxy_join )
+{
+ ib_net64_t port_guid;
+ osm_mcm_port_t *p_mcm_port;
+ cl_map_item_t *prev_item;
+ uint8_t prev_join_state;
+ uint8_t prev_scope;
+
+ p_mcm_port = osm_mcm_port_new( p_port_gid, join_state, proxy_join );
+ if( p_mcm_port )
+ {
+ port_guid = p_port_gid->unicast.interface_id;
+
+ /*
+ prev_item = cl_qmap_insert(...
+ Pointer to the item in the map with the specified key. If insertion
+ was successful, this is the pointer to the item. If an item with the
+ specified key already exists in the map, the pointer to that item is
+ returned.
+ */
+ prev_item = cl_qmap_insert(&p_mgrp->mcm_port_tbl,
+ port_guid, &p_mcm_port->map_item );
+
+ /* if already exists - revert the insertion and only update join state */
+ if( prev_item != &p_mcm_port->map_item )
+ {
+
+ osm_mcm_port_delete( p_mcm_port );
+ p_mcm_port =(osm_mcm_port_t *) prev_item;
+
+ /*
+ o15.0.1.11
+ Join state of the end portshould be the or of the
+ previous setting with the current one
+ */
+ ib_member_get_scope_state(p_mcm_port->scope_state, &prev_scope, &prev_join_state);
+ p_mcm_port->scope_state =
+ ib_member_set_scope_state(prev_scope, prev_join_state | join_state);
+
+ } else {
+ /* track the fact we modified the group ports */
+ p_mgrp->last_change_id++;
+ }
+ }
+
+ return( p_mcm_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_remove_port(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid )
+{
+ cl_map_item_t *p_map_item;
+
+ CL_ASSERT(p_mgrp);
+
+ p_map_item = cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid );
+
+ if( p_map_item != cl_qmap_end( &p_mgrp->mcm_port_tbl ) )
+ {
+ cl_qmap_remove_item( &p_mgrp->mcm_port_tbl,
+ p_map_item );
+ osm_mcm_port_delete((osm_mcm_port_t*)p_map_item);
+
+ /* track the fact we modified the group */
+ p_mgrp->last_change_id++;
+ }
+
+ /*
+ no more ports so the group will be deleted after re-route
+ but only if it is not a well known group and not already deleted
+ */
+ if ((cl_is_qmap_empty( &p_mgrp->mcm_port_tbl )) &&
+ (p_mgrp->well_known == FALSE) &&
+ (p_mgrp->to_be_deleted == FALSE))
+ {
+ p_mgrp->to_be_deleted = TRUE;
+
+ /* Send a Report to any InformInfo registered for
+ Trap 67 : MCGroup delete */
+ osm_mgrp_send_delete_notice( p_subn, p_log, p_mgrp);
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mgrp_is_port_present(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid,
+ OUT osm_mcm_port_t ** const pp_mcm_port)
+{
+ cl_map_item_t *p_map_item;
+
+ CL_ASSERT(p_mgrp);
+
+ p_map_item = cl_qmap_get(&p_mgrp->mcm_port_tbl,
+ port_guid);
+
+ if (p_map_item != cl_qmap_end(&p_mgrp->mcm_port_tbl))
+ {
+ if (pp_mcm_port)
+ *pp_mcm_port = (osm_mcm_port_t *)p_map_item;
+ return TRUE;
+ }
+ if (pp_mcm_port)
+ *pp_mcm_port = NULL;
+ return FALSE;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mgrp_apply_func_sub(
+ const osm_mgrp_t* const p_mgrp,
+ const osm_mtree_node_t* const p_mtn,
+ osm_mgrp_func_t p_func,
+ void* context )
+{
+ uint8_t i = 0;
+ uint8_t max_children;
+ osm_mtree_node_t* p_child_mtn;
+
+ /*
+ Call the user, then recurse.
+ */
+ p_func( p_mgrp, p_mtn, context );
+
+ max_children = osm_mtree_node_get_max_children( p_mtn );
+ for( i = 0; i < max_children; i++ )
+ {
+ p_child_mtn = osm_mtree_node_get_child( p_mtn, i );
+ if( p_child_mtn )
+ __osm_mgrp_apply_func_sub( p_mgrp, p_child_mtn, p_func, context );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_apply_func(
+ const osm_mgrp_t* const p_mgrp,
+ osm_mgrp_func_t p_func,
+ void* context )
+{
+ osm_mtree_node_t* p_mtn;
+
+ CL_ASSERT( p_mgrp );
+ CL_ASSERT( p_func );
+
+ p_mtn = p_mgrp->p_root;
+
+ if( p_mtn )
+ __osm_mgrp_apply_func_sub( p_mgrp, p_mtn, p_func, context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_delete_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp )
+{
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mgrp_send_delete_notice );
+
+ /* prepare the needed info */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type(¬ice, CL_NTOH32(4)); /* A Class Manager generator */
+ notice.g_or_v.generic.trap_num = CL_HTON16(67); /* delete of mcg */
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_subn->sm_base_lid;
+ /* following o14-12.1.11 and table 120 p726 */
+ /* we need to provide the MGID */
+ cl_memcpy(&(notice.data_details.ntc_64_67.gid),
+ &(p_mgrp->mcmember_rec.mgid),
+ sizeof(ib_gid_t));
+
+ /* According to page 653 - the issuer gid in this case of trap
+ is the SM gid, since the SM is the initiator of this trap. */
+ notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_log, p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mgrp_send_delete_notice: ERR 7601: "
+ "Error sending trap reports (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_create_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp )
+{
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+
+
+ OSM_LOG_ENTER( p_log, osm_mgrp_send_create_notice );
+
+ /* prepare the needed info */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* Generic SubnMgt type */
+ ib_notice_set_prod_type(¬ice, CL_HTON32(4)); /* A Class Manager generator */
+ notice.g_or_v.generic.trap_num = CL_HTON16(66); /* create of mcg */
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_subn->sm_base_lid;
+ /* following o14-12.1.11 and table 120 p726 */
+ /* we need to provide the MGID */
+ cl_memcpy(&(notice.data_details.ntc_64_67.gid),
+ &(p_mgrp->mcmember_rec.mgid),
+ sizeof(ib_gid_t));
+
+ /* According to page 653 - the issuer gid in this case of trap
+ is the SM gid, since the SM is the initiator of this trap. */
+ notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_log, p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mgrp_send_create_notice: ERR 7602: "
+ "Error sending trap reports (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_node_t.
+ * This object represents an Infiniband Node.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_init_physp(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_physp_t *p_physp;
+ ib_net64_t port_guid;
+ ib_smp_t *p_smp;
+ ib_node_info_t *p_ni;
+ uint8_t port_num;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_guid = p_ni->port_guid;
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ osm_physp_init( p_physp, port_guid, port_num, p_node,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count, p_smp->initial_path );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t*
+osm_node_new(
+ IN const osm_madw_t* const p_madw )
+{
+ osm_node_t *p_node;
+ ib_smp_t *p_smp;
+ ib_node_info_t *p_ni;
+ uint8_t port_num;
+ uint8_t i;
+ uint32_t size;
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ /*
+ The node object already contains one physical port object.
+ Therefore, subtract 1 from the number of physical ports
+ used by the switch. This is not done for CA's since they
+ need to occupy 1 more physp than they physically have since
+ we still reserve room for a "port 0".
+ */
+ size = p_ni->num_ports;
+
+ p_node = cl_zalloc( sizeof(*p_node) + sizeof(osm_physp_t) * size );
+ if( p_node != NULL )
+ {
+ p_node->node_info = *p_ni;
+ p_node->physp_tbl_size = size + 1;
+
+ /*
+ Construct Physical Port objects owned by this Node.
+ Then, initialize the Physical Port through with we
+ discovered this port.
+ For switches, all ports have the same GUID.
+ For HCA's each port has a different GUID, so we only
+ know the GUID for the port that responded to our
+ Get(NodeInfo).
+ */
+ for( i = 0; i < p_node->physp_tbl_size; i++ )
+ osm_physp_construct( osm_node_get_physp_ptr( p_node, i ) );
+
+ osm_node_init_physp( p_node, p_madw );
+ }
+
+ return( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_destroy(
+ IN osm_node_t *p_node )
+{
+ uint16_t i;
+
+ /* Cleanup all PhysPorts */
+ if( p_node != NULL )
+ {
+ /*
+ Cleanup all physports
+ */
+ for( i = 0; i < p_node->physp_tbl_size; i++ )
+ {
+ osm_physp_t *p_physp = osm_node_get_physp_ptr( p_node, i );
+ if (p_physp)
+ osm_physp_destroy( p_physp );
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_delete(
+ IN OUT osm_node_t** const p_node )
+{
+ osm_node_destroy( *p_node );
+ cl_free( *p_node );
+ *p_node = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_link(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ p_remote_physp = osm_node_get_physp_ptr( p_remote_node,
+ remote_port_num );
+
+ osm_physp_link( p_physp, p_remote_physp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_unlink(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+ if( osm_node_link_exists( p_node, port_num,
+ p_remote_node, remote_port_num ) )
+ {
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ p_remote_physp = osm_node_get_physp_ptr( p_remote_node,
+ remote_port_num );
+
+ osm_physp_unlink( p_physp, p_remote_physp );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_link_exists(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ p_remote_physp = osm_node_get_physp_ptr( p_remote_node,
+ remote_port_num );
+
+ return( osm_physp_link_exists( p_physp, p_remote_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_link_has_valid_ports(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ p_remote_physp = osm_node_get_physp_ptr( p_remote_node,
+ remote_port_num );
+
+ return( osm_physp_is_valid( p_physp ) &&
+ osm_physp_is_valid( p_remote_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_has_any_link(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num )
+{
+ osm_physp_t *p_physp;
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ return( osm_physp_has_any_link( p_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t*
+osm_node_get_remote_node(
+ IN const osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ OUT uint8_t *p_remote_port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ if( !osm_physp_has_any_link( p_physp ) )
+ return( NULL );
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_port_num )
+ *p_remote_port_num = osm_physp_get_port_num( p_remote_physp );
+
+ return( osm_physp_get_node_ptr( p_remote_physp ) );
+}
+
+/**********************************************************************
+ The lock must be held before calling this function.
+**********************************************************************/
+ib_net16_t
+osm_node_get_remote_base_lid(
+ IN const osm_node_t* const p_node,
+ IN const uint32_t port_num )
+{
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ if( osm_physp_is_valid( p_physp ) )
+ {
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ return( osm_physp_get_base_lid( p_remote_physp ) );
+ }
+
+ return( 0 );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nd_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_process_nd(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const ib_node_desc_t* const p_nd )
+{
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_nd_rcv_process_nd );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ cl_memcpy( desc, p_nd, sizeof(*p_nd) );
+ /* Guarantee null termination before printing. */
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_nd_rcv_process_nd: "
+ "Node 0x%" PRIx64 "\n\t\t\t\tDescription = %s.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node )), desc );
+ }
+
+ cl_memcpy( &p_node->node_desc.description, p_nd, sizeof(*p_nd) );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_construct(
+ IN osm_nd_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_destroy(
+ IN osm_nd_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_init(
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_nd_rcv_init );
+
+ osm_nd_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_process(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_node_desc_t *p_nd;
+ ib_smp_t *p_smp;
+ osm_node_t *p_node;
+ ib_net64_t node_guid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_nd = (ib_node_desc_t*)ib_smp_get_payload_ptr( p_smp );
+
+ /*
+ Acquire the node object and add the node description.
+ */
+
+ node_guid = osm_madw_get_nd_context_ptr( p_madw )->node_guid;
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, node_guid );
+
+ if( p_node == (osm_node_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nd_rcv_process: ERR 0B01: "
+ "NodeDescription received for nonexistent node "
+ "0x%" PRIx64 ".\n", cl_ntoh64(node_guid) );
+ }
+ else
+ {
+ __osm_nd_rcv_process_nd( p_rcv, p_node, p_nd );
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nd_rcv_ctrl_t.
+ * This object represents the NodeDescription request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x601
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_nd_rcv_process( ((osm_nd_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_construct(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_destroy(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl,
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_nd_rcv_ctrl_init );
+
+ osm_nd_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_DESC,
+ __osm_nd_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_nd_rcv_ctrl_init: ERR 0C01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_set_links(
+ IN const osm_ni_rcv_t* const p_rcv,
+ osm_node_t* p_node,
+ const uint8_t port_num,
+ const osm_ni_context_t* const p_ni_context )
+{
+ cl_qmap_t *p_guid_tbl;
+ osm_node_t *p_neighbor_node;
+ osm_node_t *p_old_neighbor_node;
+ uint8_t old_neighbor_port_num;
+ osm_physp_t *p_physp, *p_old_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_set_links );
+
+ /*
+ A special case exists in which the node we're trying to
+ link is our own node. In this case, the guid value in
+ the ni_context will be zero.
+ */
+ if( p_ni_context->node_guid != 0 )
+ {
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_neighbor_node = (osm_node_t*)cl_qmap_get( p_guid_tbl,
+ p_ni_context->node_guid );
+ if( p_neighbor_node == (osm_node_t*)cl_qmap_end( p_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D10: "
+ "Unexpected removal of neighbor node "
+ "0x%" PRIx64 ".\n",
+ cl_ntoh64( p_ni_context->node_guid ) );
+ }
+ else
+ {
+ /*
+ We have seen this neighbor node before, but we might
+ not have seen this port on the neighbor node before.
+ We should not set links to an uninitialized port on the
+ neighbor, so check validity up front. If it's not
+ valid, do nothing, since we'll see this link again
+ when we probe the neighbor.
+ */
+ if( osm_node_link_has_valid_ports( p_node, port_num,
+ p_neighbor_node, p_ni_context->port_num ) )
+ {
+ if( osm_node_link_exists( p_node, port_num,
+ p_neighbor_node, p_ni_context->port_num ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Link already exists.\n" );
+ }
+ else
+ {
+ if( osm_node_has_any_link( p_node, port_num ) )
+ {
+ /*
+ Uh oh...
+ */
+ p_old_neighbor_node = osm_node_get_remote_node(
+ p_node, port_num, &old_neighbor_port_num );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D01: "
+ "Overriding existing link to:"
+ "node 0x%" PRIx64 ", port number 0x%X connected to:\n"
+ "\t\t\t\told node 0x%" PRIx64 ", "
+ "port number 0x%X.\n"
+ "\t\t\t\tnew node 0x%" PRIx64 ", "
+ "port number 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( osm_node_get_node_guid(
+ p_old_neighbor_node ) ),
+ old_neighbor_port_num ,
+ cl_ntoh64( p_ni_context->node_guid ),
+ p_ni_context->port_num
+ );
+
+ if (osm_log_is_active(p_rcv->p_log, OSM_LOG_ERROR))
+ {
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ if (p_physp)
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ OSM_LOG_ERROR);
+
+ p_old_physp = osm_node_get_physp_ptr(
+ p_old_neighbor_node,
+ old_neighbor_port_num);
+ if (p_old_physp)
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr( p_old_physp ),
+ OSM_LOG_ERROR);
+ }
+ }
+
+ /*
+ When there are only two nodes with exact same guids (connected back to
+ back) - the previous check for duplicated guid will not catch them.
+ But the link will be from the port to itself ...
+ Enhanced Port 0 is an exception to this
+ */
+ if ((osm_node_get_node_guid( p_node ) == p_ni_context->node_guid) &&
+ (port_num == p_ni_context->port_num) &&
+ (port_num != 0))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D18: "
+ "Duplicate GUID found by link from a port to itself:"
+ "node 0x%" PRIx64 ", port number 0x%X \n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num );
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ if (p_physp)
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(p_physp),
+ OSM_LOG_ERROR);
+ }
+ else
+ {
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Creating new link between: "
+ "\n\t\t\t\tnode 0x%" PRIx64 ", "
+ "port number 0x%X and"
+ "\n\t\t\t\tnode 0x%" PRIx64 ", "
+ "port number 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( p_ni_context->node_guid ),
+ p_ni_context->port_num );
+ }
+
+ CL_ASSERT( osm_node_get_node_guid( p_neighbor_node ) ==
+ p_ni_context->node_guid );
+
+ osm_node_link( p_node, port_num, p_neighbor_node,
+ p_ni_context->port_num );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Nothing to link for our own node 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_node(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_physp;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_node );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ CL_ASSERT( p_node );
+
+ /*
+ Request PortInfo & NodeDescription attributes for the port
+ that responded to the NodeInfo attribute.
+ Because this is a channel adapter or router, we are
+ not allowed to request PortInfo for the other ports.
+ Set the context union properly, so the recipient
+ knows which node & port are relevant.
+ */
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+ osm_dr_path_get_bind_handle(
+ osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+ context.pi_context.node_guid = p_ni->node_guid;
+ context.pi_context.port_guid = p_ni->port_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new_node: ERR 0D02: "
+ "Failure initiating PortInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_get_node_desc(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_physp;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_get_node_desc );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+
+ /*
+ Request PortInfo & NodeDescription attributes for the port
+ that responded to the NodeInfo attribute.
+ Because this is a channel adapter or router, we are
+ not allowed to request PortInfo for the other ports.
+ Set the context union properly, so the recipient
+ knows which node & port are relevant.
+ */
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+ osm_dr_path_get_bind_handle(
+ osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+ context.nd_context.node_guid = osm_node_get_node_guid( p_node );
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_NODE_DESC,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_get_node_desc: ERR 0D03: "
+ "Failure initiating NodeDescription request (%s).\n",
+ ib_get_err_str(status));
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_ca(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_ca );
+
+ __osm_ni_rcv_process_new_node( p_rcv, p_node, p_madw );
+
+ /*
+ A node guid of 0 is the corner case that indicates
+ we discovered our own node. Initialize the subnet
+ object with the SM's own port guid.
+ */
+ if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 )
+ {
+ p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_ca_port(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_port_t *p_port_check;
+ cl_qmap_t *p_guid_tbl;
+ osm_madw_context_t context;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+ ib_api_status_t status;
+ osm_dr_path_t *p_dr_path;
+ osm_bind_handle_t h_bind;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_ca_port );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ h_bind = osm_madw_get_bind_handle( p_madw );
+
+ /*
+ Determine if we have encountered this node through a
+ previously undiscovered port. If so, build the new
+ port object.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, p_ni->port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_ca_port: "
+ "Creating new Port object with GUID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( p_ni->port_guid ) );
+
+ osm_node_init_physp( p_node, p_madw );
+
+ p_port = osm_port_new( p_ni, p_node );
+ if( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_ca_port: ERR 0D04: "
+ "Unable to create new port object.\n" );
+ goto Exit;
+ }
+
+ /*
+ Add the new port object to the database.
+ */
+ p_port_check = (osm_port_t*)cl_qmap_insert( p_guid_tbl,
+ p_ni->port_guid, &p_port->map_item );
+ if( p_port_check != p_port )
+ {
+ /*
+ We should never be here!
+ Somehow, this port GUID already exists in the table.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_ca_port: ERR 0D12: "
+ "Port 0x%" PRIx64 " already in the database!.\n",
+ cl_ntoh64( p_ni->port_guid ) );
+
+ osm_port_delete( &p_port );
+ goto Exit;
+ }
+
+ /* If we are a master, then this means the port is new on the subnet.
+ Add it to the new_ports_list - need to send trap 64 on these ports.
+ The condition that we are master is true, since if we are in discovering
+ state (meaning we woke up from standby or we are just initializing),
+ then these ports may be new to us, but are not new on the subnet.
+ If we are master, then the subnet as we know it is the updated one,
+ and any new ports we encounter should cause trap 64. C14-72.1.1 */
+ if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ cl_status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_ca_port: ERR 0D08: "
+ "Error %s adding to list.\n",
+ CL_STATUS_MSG( cl_status ) );
+ osm_port_delete( &p_port );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_ca_port: "
+ "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+ cl_ntoh64(osm_node_get_node_guid( p_port->p_node )) );
+ }
+ }
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ }
+ else
+ {
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ /*
+ Update the DR Path to the port,
+ in case the old one is no longer available.
+ */
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+ osm_dr_path_init( p_dr_path, h_bind, p_smp->hop_count,
+ p_smp->initial_path );
+ }
+
+ context.pi_context.node_guid = p_ni->node_guid;
+ context.pi_context.port_guid = p_ni->port_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_ca_port: ERR 0D13: "
+ "Failure initiating PortInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_existing_ca(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_ca );
+
+ __osm_ni_rcv_process_ca_port( p_rcv, p_node, p_madw );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_router(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_router );
+
+ __osm_ni_rcv_process_new_node( p_rcv, p_node, p_madw );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_ni_rcv_process_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_dr_path_t dr_path;
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_switch );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ osm_dr_path_init( &dr_path,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count,
+ p_smp->initial_path );
+
+ context.si_context.node_guid = osm_node_get_node_guid( p_node );
+ context.si_context.set_method = FALSE;
+ context.si_context.light_sweep = FALSE;
+
+ /* Request a SwitchInfo attribute */
+ status = osm_req_get( p_rcv->p_gen_req,
+ &dr_path,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue despite error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_switch: ERR 0D06: "
+ "Failure initiating SwitchInfo request (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_existing_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_sw_guid_tbl;
+ ib_net64_t node_guid;
+ osm_switch_t *p_sw;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_switch );
+
+ /*
+ If this switch has already been probed during this sweep,
+ then don't bother reprobing it.
+ There is one exception - if the node has been visited, but
+ for some reason we don't have the switch object (this can happen
+ if the SwitchInfo mad didn't reach the SM) then we want
+ to retry to probe the switch.
+ */
+ if( osm_node_discovery_count_get( p_node ) == 1 )
+ __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+ else
+ {
+ /* Make sure we have SwitchInfo on this node */
+ p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+ node_guid = osm_node_get_node_guid( p_node );
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl,
+ node_guid );
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) ||
+ osm_switch_discovery_count_get( p_sw ) == 0 )
+ {
+ /* we don't have the SwitchInfo - retry to get it */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_existing_switch: "
+ "Retry to get SwitchInfo on node GUID:0x%"
+ PRIx64 ".\n", cl_ntoh64(node_guid) );
+ __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_switch );
+
+ __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+
+ /*
+ A node guid of 0 is the corner case that indicates
+ we discovered our own node. Initialize the subnet
+ object with the SM's own port guid.
+ */
+ if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 )
+ {
+ p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must NOT be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_node_t *p_node;
+ osm_node_t *p_node_check;
+ osm_port_t *p_port;
+ osm_port_t *p_port_check;
+ cl_qmap_t *p_node_guid_tbl;
+ cl_qmap_t *p_port_guid_tbl;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_ni_context_t *p_ni_context;
+ uint8_t port_num;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ p_ni_context = osm_madw_get_ni_context_ptr( p_madw );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ osm_dump_smp_dr_path( p_rcv->p_log, p_smp, OSM_LOG_VERBOSE );
+
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_new: "
+ "Discovered new %s node,"
+ "\n\t\t\t\tGUID = 0x%" PRIx64 ", TID = 0x%" PRIx64 ".\n",
+ ib_get_node_type_str( p_ni->node_type ),
+ cl_ntoh64( p_ni->node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+
+ p_node = osm_node_new( p_madw );
+ if( p_node == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D07: "
+ "Unable to create new node object.\n" );
+ goto Exit;
+ }
+
+ /*
+ Create a new Port object to represent this node's physical
+ ports in the port table.
+ */
+ p_port = osm_port_new( p_ni, p_node );
+ if( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D14: "
+ "Unable to create new port object.\n" );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+
+ p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_port_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+ /*
+ Add the new port object to the database.
+ */
+ p_port_check = (osm_port_t*)cl_qmap_insert( p_port_guid_tbl,
+ p_ni->port_guid, &p_port->map_item );
+ if( p_port_check != p_port )
+ {
+ /*
+ We should never be here!
+ Somehow, this port GUID already exists in the table.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D15: "
+ "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n",
+ cl_ntoh64( p_ni->port_guid ) );
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(
+ osm_port_get_default_phys_ptr ( p_port) ),
+ OSM_LOG_ERROR);
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(
+ osm_port_get_default_phys_ptr ( p_port_check) ),
+ OSM_LOG_ERROR);
+
+ osm_port_delete( &p_port );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+ /* If we are a master, then this means the port is new on the subnet.
+ Add it to the new_ports_list - need to send trap 64 on these ports.
+ The condition that we are master is true, since if we are in discovering
+ state (meaning we woke up from standby or we are just initializing),
+ then these ports may be new to us, but are not new on the subnet.
+ If we are master, then the subnet as we know it is the updated one,
+ and any new ports we encounter should cause trap 64. C14-72.1.1 */
+ if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D05: "
+ "Error %s adding to list.\n",
+ CL_STATUS_MSG(status ) );
+ osm_port_delete( &p_port );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_new: "
+ "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+ cl_ntoh64(osm_node_get_node_guid( p_port->p_node )) );
+ }
+ }
+
+ p_node_check = (osm_node_t*)cl_qmap_insert( p_node_guid_tbl,
+ p_ni->node_guid, &p_node->map_item );
+ if( p_node_check != p_node )
+ {
+ /*
+ This node must have been inserted by another thread.
+ This is unexpected, but is not an error.
+ We can simply clean-up, since the other thread will
+ see this processing through to completion.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_new: "
+ "Discovery race detected at node 0x%" PRIx64 ".\n",
+ cl_ntoh64( p_ni->node_guid ) );
+
+ osm_node_delete( &p_node );
+ p_node = p_node_check;
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+ goto Exit;
+ }
+ else
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+ osm_node_discovery_count_inc( p_node );
+ __osm_ni_rcv_get_node_desc( p_rcv, p_node, p_madw );
+
+ switch( p_ni->node_type )
+ {
+ case IB_NODE_TYPE_CA:
+ __osm_ni_rcv_process_new_ca( p_rcv, p_node, p_madw );
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ __osm_ni_rcv_process_new_switch( p_rcv, p_node, p_madw );
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ __osm_ni_rcv_process_new_router( p_rcv, p_node, p_madw );
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D16: "
+ "Unknown node type = %u with GUID = 0x%" PRIx64 ".\n",
+ p_ni->node_type, cl_ntoh64( p_ni->node_guid ) );
+ break;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_existing(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_ni_context_t *p_ni_context;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ p_ni_context = osm_madw_get_ni_context_ptr( p_madw );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_existing: "
+ "Rediscovered %s node 0x%" PRIx64
+ "\n\t\t\t\tTID = 0x%" PRIx64
+ ", discovered %u times already.\n",
+ ib_get_node_type_str(p_ni->node_type),
+ cl_ntoh64( p_ni->node_guid ),
+ cl_ntoh64( p_smp->trans_id ),
+ osm_node_discovery_count_get( p_node ) );
+ }
+
+ /*
+ If we haven't already encountered this existing node
+ on this particular sweep, then process further.
+ */
+ osm_node_discovery_count_inc( p_node );
+
+ switch( p_ni->node_type )
+ {
+ case IB_NODE_TYPE_ROUTER:
+ /* Not supported yet. */
+ break;
+
+ case IB_NODE_TYPE_CA:
+ __osm_ni_rcv_process_existing_ca( p_rcv, p_node, p_madw );
+ break;
+
+ case IB_NODE_TYPE_SWITCH:
+ __osm_ni_rcv_process_existing_switch( p_rcv, p_node, p_madw );
+ break;
+
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing: ERR 0D09: "
+ "Unknown node type = %u with GUID = 0x%" PRIx64 ".\n",
+ p_ni->node_type, cl_ntoh64( p_ni->node_guid ) );
+ break;
+ }
+
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_construct(
+ IN osm_ni_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_destroy(
+ IN osm_ni_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_init(
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_ni_rcv_init );
+
+ osm_ni_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_gen_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_process(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_node_t *p_node;
+ boolean_t process_new_flag = FALSE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ if (p_ni->node_guid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_process: ERR 0D16: "
+ "Got Zero Node GUID! Found on the directed route:\n");
+ osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+ goto Exit;
+ }
+
+ if (p_ni->port_guid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_process: ERR 0D17: "
+ "Got Zero Port GUID! Found on the directed route:\n");
+ osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+ goto Exit;
+ }
+ /*
+ Determine if this node has already been discovered,
+ and process accordingly.
+ During processing of this node, hold the shared lock.
+ */
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, p_ni->node_guid );
+
+ osm_dump_node_info( p_rcv->p_log, p_ni, OSM_LOG_DEBUG );
+
+ if( p_node == (osm_node_t*)cl_qmap_end(p_guid_tbl) )
+ {
+ __osm_ni_rcv_process_new( p_rcv, p_madw );
+ process_new_flag = TRUE;
+ }
+ else
+ __osm_ni_rcv_process_existing( p_rcv, p_node, p_madw );
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /*
+ * If we processed a new node - need to signal to the state_mgr that
+ * change detected. BUT - we cannot call the osm_state_mgr_process
+ * from within the lock of p_rcv->p_lock (can cause a deadlock).
+ */
+ if ( process_new_flag )
+ osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_CHANGE_DETECTED );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ni_rcv_ctrl_t.
+ * This object represents the NodeInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_ni_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_ni_rcv_process( ((osm_ni_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_construct(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_destroy(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_ctrl_init(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl,
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_ni_rcv_ctrl_init );
+
+ osm_ni_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_INFO,
+ __osm_ni_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_ctrl_init: ERR 0E01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_opensm_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_signal_osd.h>
+#include <opensm/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_vl15intf.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_construct(
+ IN osm_opensm_t * const p_osm )
+{
+ cl_memclr( p_osm, sizeof( *p_osm ) );
+ osm_subn_construct( &p_osm->subn );
+ osm_sm_construct( &p_osm->sm );
+ osm_sa_construct( &p_osm->sa );
+ osm_db_construct( &p_osm->db );
+ osm_mad_pool_construct( &p_osm->mad_pool );
+ osm_vl15_construct( &p_osm->vl15 );
+ osm_log_construct( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_destroy(
+ IN osm_opensm_t * const p_osm )
+{
+
+ /* in case of shutdown through exit proc - no ^C */
+ osm_exit_flag = TRUE;
+
+ /*
+ * First of all - Clear the is_sm bit.
+ */
+ if( p_osm->sm.mad_ctrl.h_bind )
+ osm_vendor_set_sm( p_osm->sm.mad_ctrl.h_bind, FALSE );
+
+ /* shut down the SA
+ * - unbind from Q1 Messages and
+ */
+ osm_sa_shutdown( &p_osm->sa );
+
+ /* shut down the SM
+ * - make sure the SM sweeper thread exited
+ * - unbind from Q0 Messages and
+ */
+ osm_sm_shutdown( &p_osm->sm );
+
+ /* shut down the dispatcher - so no new messages cross */
+ cl_disp_shutdown( &p_osm->disp );
+
+ /* cleanup all messages on VL15 fifo that were not sent yet */
+ osm_vl15_shutdown( &p_osm->vl15, &p_osm->mad_pool );
+
+ /* lock the whole thing so we do not get any requests etc */
+ cl_plock_excl_acquire( &p_osm->lock );
+
+ /* do the destruction in reverse init order */
+ updn_destroy( p_osm->p_updn_ucast_routing );
+ osm_sa_destroy( &p_osm->sa );
+ osm_sm_destroy( &p_osm->sm );
+ osm_db_destroy( &p_osm->db );
+ osm_vl15_destroy( &p_osm->vl15, &p_osm->mad_pool );
+ osm_mad_pool_destroy( &p_osm->mad_pool );
+ osm_vendor_delete( &p_osm->p_vendor );
+ osm_subn_destroy( &p_osm->subn );
+ cl_disp_destroy( &p_osm->disp );
+
+ cl_plock_release( &p_osm->lock );
+ cl_plock_destroy( &p_osm->lock );
+
+ cl_mem_display( );
+
+ osm_log_destroy( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_opensm_create_mcgroups(
+ IN osm_opensm_t * const p_osm,
+ IN const osm_subn_opt_t * const p_opt )
+{
+ OSM_LOG_ENTER( &p_osm->log, osm_opensm_create_mcgroups );
+ osm_sa_create_template_record_ipoib( &p_osm->sa, p_opt );
+ OSM_LOG_EXIT( &p_osm->log );
+}
+
+/**********************************************************************
+ * SHUT DOWN IS CONTROLLED BY A GLOBAL EXIT FLAG
+ **********************************************************************/
+#ifndef __WIN__
+static osm_opensm_t *__p_osm_to_signal;
+
+void
+__sig_handler(
+ int signum )
+{
+ static int got_signal = 0;
+
+ if( signum != SIGHUP )
+ {
+ if( !got_signal )
+ {
+ got_signal++;
+ printf( "OpenSM: Got signal %d - exiting...\n", signum );
+ osm_exit_flag = 1;
+ }
+ }
+ else
+ {
+ /* a HUP signal should only start a new heavy sweep */
+ __p_osm_to_signal->subn.force_immediate_heavy_sweep = TRUE;
+ osm_state_mgr_process( &__p_osm_to_signal->sm.state_mgr,
+ OSM_SIGNAL_SWEEP );
+ }
+}
+
+void
+osm_reg_sig_handler(
+ IN osm_opensm_t * const p_osm )
+{
+ __p_osm_to_signal = p_osm;
+ cl_reg_sig_hdl( SIGINT, __sig_handler );
+ cl_reg_sig_hdl( SIGTERM, __sig_handler );
+ cl_reg_sig_hdl( SIGHUP, __sig_handler );
+ osm_exit_flag = 0;
+
+ return;
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_init(
+ IN osm_opensm_t * const p_osm,
+ IN const osm_subn_opt_t * const p_opt )
+{
+ ib_api_status_t status;
+
+ /* Can't use log macros here, since we're initializing the log. */
+ osm_opensm_construct( p_osm );
+
+ status = osm_log_init( &p_osm->log, p_opt->force_log_flush,
+ p_opt->log_flags, p_opt->log_file );
+ if( status != IB_SUCCESS )
+ return ( status );
+
+ /* If there is a log level defined - add the OSM_VERSION to it. */
+ osm_log( &p_osm->log,
+ osm_log_get_level( &p_osm->log ) & ( OSM_LOG_SYS ^ 0xFF ), "%s\n",
+ OSM_VERSION );
+ /* Write the OSM_VERSION to the SYS_LOG */
+ osm_log( &p_osm->log, OSM_LOG_SYS, "%s\n", OSM_VERSION ); /* Format Waived */
+
+ osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: [\n" ); /* Format Waived */
+
+ status = cl_plock_init( &p_osm->lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ if( p_opt->single_thread )
+ {
+ osm_log( &p_osm->log, OSM_LOG_INFO,
+ "osm_opensm_init: Forcing single threaded dispatcher.\n" );
+ status = cl_disp_init( &p_osm->disp, 1, "opensm" );
+ }
+ else
+ {
+ /*
+ * Normal behavior is to initialize the dispatcher with
+ * one thread per CPU, as specified by a thread count of '0'.
+ */
+ status = cl_disp_init( &p_osm->disp, 0, "opensm" );
+ }
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+ status = osm_subn_init( &p_osm->subn, p_opt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ p_osm->p_vendor =
+ osm_vendor_new( &p_osm->log, p_opt->transaction_timeout );
+ if( p_osm->p_vendor == NULL )
+ {
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ status = osm_mad_pool_init( &p_osm->mad_pool, &p_osm->log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vl15_init( &p_osm->vl15,
+ p_osm->p_vendor,
+ &p_osm->log, &p_osm->stats, p_opt->max_wire_smps );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ /* the DB is in use by the SM and SA so init before */
+ status = osm_db_init( &p_osm->db, &p_osm->log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sm_init( &p_osm->sm,
+ &p_osm->subn,
+ &p_osm->db,
+ p_osm->p_vendor,
+ &p_osm->mad_pool,
+ &p_osm->vl15,
+ &p_osm->log,
+ &p_osm->stats, &p_osm->disp, &p_osm->lock );
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sa_init( &p_osm->sm,
+ &p_osm->sa,
+ &p_osm->subn,
+ p_osm->p_vendor,
+ &p_osm->mad_pool,
+ &p_osm->log,
+ &p_osm->stats, &p_osm->disp, &p_osm->lock );
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ osm_opensm_create_mcgroups( p_osm, p_opt );
+
+ /* HACK - the UpDown manager should have been a part of the osm_sm_t */
+ /* Init updn struct */
+ p_osm->p_updn_ucast_routing = updn_construct( );
+ status = updn_init( p_osm->p_updn_ucast_routing );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: ]\n" ); /* Format Waived */
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_bind(
+ IN osm_opensm_t * const p_osm,
+ IN const ib_net64_t guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( &p_osm->log, osm_opensm_bind );
+
+ status = osm_sm_bind( &p_osm->sm, guid );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sa_bind( &p_osm->sa, guid );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ Exit:
+ OSM_LOG_EXIT( &p_osm->log );
+ return ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of opensm pkey manipulation functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_construct(
+ IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+ cl_ptr_vector_construct( &p_pkey_tbl->blocks );
+ cl_map_construct( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_destroy(
+ IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+ uint16_t num_blocks, i;
+ num_blocks = (uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks ));
+ for (i = 0; i < num_blocks; i++)
+ cl_free(cl_ptr_vector_get( &p_pkey_tbl->blocks, i ));
+ cl_ptr_vector_destroy( &p_pkey_tbl->blocks );
+
+ cl_map_remove_all( &p_pkey_tbl->keys );
+ cl_map_destroy( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_pkey_tbl_init(
+ IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+ ib_pkey_table_t *p_pkey_block;
+ /*
+ we always need one block to be pre-allocated for the sake of
+ empty table test
+ */
+ cl_ptr_vector_init( &p_pkey_tbl->blocks, 1, 1);
+ p_pkey_block = (ib_pkey_table_t *)cl_zalloc(sizeof(ib_pkey_table_t));
+ if (! p_pkey_block)
+ {
+ return(IB_ERROR);
+ }
+
+ cl_ptr_vector_set(&p_pkey_tbl->blocks, 0, p_pkey_block);
+
+ /* deal with the map */
+ cl_map_init( &p_pkey_tbl->keys, 1 );
+ return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_pkey_tbl_set(
+ IN osm_pkey_tbl_t *p_pkey_tbl,
+ IN uint16_t block,
+ IN ib_pkey_table_t *p_tbl)
+{
+ uint16_t b, i;
+ ib_pkey_table_t *p_pkey_block;
+ uint16_t *p_prev_pkey;
+ ib_net16_t pkey;
+
+ /* make sure the block is allocated */
+ if (cl_ptr_vector_get_size( &p_pkey_tbl->blocks ) > block)
+ p_pkey_block =
+ (ib_pkey_table_t *)cl_ptr_vector_get( &p_pkey_tbl->blocks, block );
+ else
+ p_pkey_block = NULL;
+
+ if ( !p_pkey_block )
+ {
+ p_pkey_block = (ib_pkey_table_t *)cl_zalloc(sizeof(ib_pkey_table_t));
+ cl_ptr_vector_set( &p_pkey_tbl->blocks, block, p_pkey_block );
+ }
+
+ /* sets the block values */
+ cl_memcpy( p_pkey_block, p_tbl, sizeof(ib_pkey_table_t) );
+
+ /*
+ NOTE: as the spec does not require uniqueness of PKeys in
+ tables there is no other way but to refresh the entire keys map.
+
+ Moreover, if the same key exists but with full membership it should have
+ precedence on the key with partial membership !
+ */
+ cl_map_remove_all( &p_pkey_tbl->keys );
+
+ for (b = 0; b < cl_ptr_vector_get_size( &p_pkey_tbl->blocks ); b++)
+ {
+
+ p_pkey_block = cl_ptr_vector_get( &p_pkey_tbl->blocks, b );
+ if (! p_pkey_block) continue;
+
+ for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++)
+ {
+ pkey = p_pkey_block->pkey_entry[i];
+ if (ib_pkey_is_invalid(pkey)) continue;
+
+ /*
+ ignore the PKey Full Member bit in the key but store
+ the pointer to the table element as the map value
+ */
+ p_prev_pkey =
+ cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base(pkey));
+
+ /* we only insert if no previous or it is not full member */
+ if ((p_prev_pkey == NULL) ||
+ (cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
+ cl_map_insert( &p_pkey_tbl->keys,
+ ib_pkey_get_base(pkey),
+ &(p_pkey_block->pkey_entry[i])
+ );
+ }
+ }
+ return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t __osm_match_pkey (
+ IN const ib_net16_t *pkey1,
+ IN const ib_net16_t *pkey2 ) {
+
+ /* if both pkeys are not full member - this is not a match */
+ if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2)))
+ return(FALSE);
+
+ /* compare if the bases are the same. if they are - then
+ this is a match */
+ if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2))
+ return(FALSE);
+
+ return(TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_physp_t* const p_physp_1,
+ IN const osm_physp_t* const p_physp_2 ) {
+
+ ib_net16_t *pkey1, *pkey2;
+ uint64_t pkey1_base, pkey2_base;
+ const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
+ cl_map_iterator_t map_iter1, map_iter2;
+
+ OSM_LOG_ENTER( p_log, osm_physp_share_pkey );
+
+ pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
+ pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);
+
+ /*
+ The spec: 10.9.2 does not require each phys port to have PKey Table.
+ So actually if it does not - we would need to use the default port
+ instead.
+
+ HACK: meanwhile we will ignore the check
+ */
+ if (cl_is_map_empty(&pkey_tbl1->keys) || cl_is_map_empty(&pkey_tbl2->keys))
+ {
+ OSM_LOG_EXIT( p_log );
+ return(TRUE);
+ }
+
+ /* we rely on the fact the map are sorted by pkey */
+ map_iter1 = cl_map_head( &pkey_tbl1->keys );
+ map_iter2 = cl_map_head( &pkey_tbl2->keys );
+
+ while ( (map_iter1 != cl_map_end( &pkey_tbl1->keys )) &&
+ (map_iter2 != cl_map_end( &pkey_tbl2->keys )))
+ {
+ pkey1 = (ib_net16_t *)cl_map_obj( map_iter1 );
+ pkey2 = (ib_net16_t *)cl_map_obj( map_iter2 );
+
+ if (__osm_match_pkey(pkey1, pkey2))
+ {
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_share_pkey: "
+ "Matched pkeys: 0x%04x 0x%04x\n",
+ cl_ntoh16(*pkey1), cl_ntoh16(*pkey2));
+ OSM_LOG_EXIT( p_log );
+ return(TRUE);
+ }
+
+ /* advance the lower value if they are no equal */
+ pkey1_base = cl_map_key( map_iter1 );
+ pkey2_base = cl_map_key( map_iter2 );
+ if (pkey2_base == pkey1_base)
+ {
+ map_iter1 = cl_map_next( map_iter1 );
+ map_iter2 = cl_map_next( map_iter2 );
+ }
+ else if (pkey2_base < pkey1_base)
+ map_iter2 = cl_map_next( map_iter2 );
+ else
+ map_iter1 = cl_map_next( map_iter1 );
+ }
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_share_pkey: "
+ "Ports do not share a pkey\n");
+
+ OSM_LOG_EXIT( p_log );
+ return(FALSE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_port_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_port_t* const p_port_1,
+ IN const osm_port_t* const p_port_2 ) {
+
+ osm_physp_t *p_physp1, *p_physp2;
+ boolean_t ret;
+
+ OSM_LOG_ENTER( p_log, osm_port_share_pkey );
+
+ if (!p_port_1 || !p_port_2) {
+ ret = FALSE;
+ goto Exit;
+ }
+
+ p_physp1 = osm_port_get_default_phys_ptr(p_port_1);
+ p_physp2 = osm_port_get_default_phys_ptr(p_port_2);
+
+ if (!p_physp1 || !p_physp2) {
+ ret = FALSE;
+ goto Exit;
+ }
+
+ ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2);
+
+Exit:
+ OSM_LOG_EXIT(p_log);
+ return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_lid_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t * const p_subn,
+ IN const ib_net16_t lid1,
+ IN const uint8_t port_num1,
+ IN const ib_net16_t lid2,
+ IN const uint8_t port_num2 ) {
+
+ osm_physp_t *p_physp1, *p_physp2;
+ osm_port_t *p_port1, *p_port2;
+ osm_node_t *p_node1, *p_node2;
+ const cl_ptr_vector_t* const p_port_lid_tbl = &(p_subn->port_lid_tbl);
+
+ OSM_LOG_ENTER( p_log, osm_lid_share_pkey );
+
+ p_port1 = cl_ptr_vector_get(p_port_lid_tbl, lid1);
+ p_port2 = cl_ptr_vector_get(p_port_lid_tbl, lid2);
+
+ p_node1 = p_port1->p_node;
+ p_node2 = p_port2->p_node;
+
+ if (osm_node_get_type( p_node1 ) == IB_NODE_TYPE_SWITCH)
+ {
+ p_physp1 = osm_node_get_physp_ptr( p_node1, port_num1 );
+ }
+ else
+ {
+ p_physp1 = osm_port_get_default_phys_ptr(p_port1);
+ }
+
+ if (osm_node_get_type( p_node2 ) == IB_NODE_TYPE_SWITCH)
+ {
+ p_physp2 = osm_node_get_physp_ptr( p_node2, port_num2 );
+ }
+ else
+ {
+ p_physp2 = osm_port_get_default_phys_ptr(p_port2);
+ }
+
+ return(osm_physp_share_pkey(p_log, p_physp1, p_physp2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_has_pkey(
+ IN osm_log_t* p_log,
+ IN const ib_net16_t pkey,
+ IN const osm_physp_t* const p_physp ) {
+
+ ib_net16_t *p_pkey, pkey_base;
+ const osm_pkey_tbl_t *pkey_tbl;
+ boolean_t res = FALSE;
+
+ OSM_LOG_ENTER( p_log, osm_physp_has_pkey );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "Search for pkey: 0x%X\n",
+ cl_ntoh16(pkey) );
+
+ /* if the pkey given is an invalid pkey - return TRUE. */
+ if(ib_pkey_is_invalid(pkey))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "Given invalid PKey - we treat it loosely and allow it.\n");
+ res = TRUE;
+ goto Exit;
+ }
+
+ pkey_base = ib_pkey_get_base(pkey);
+
+ pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
+
+ p_pkey = cl_map_get( &pkey_tbl->keys, pkey_base);
+ if (p_pkey)
+ {
+ res = TRUE;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "PKey 0x%04x was found.\n", cl_ntoh16(pkey));
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "PKey 0x%04x was not found.\n", cl_ntoh16(pkey));
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return res;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_pkey_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_construct(
+ IN osm_pkey_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_destroy(
+ IN osm_pkey_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_init(
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_pkey_rcv_init );
+
+ osm_pkey_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+
+void
+osm_pkey_rcv_process(
+ IN const osm_pkey_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_pkey_table_t *p_pkey_tbl;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ osm_pkey_context_t *p_context;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t port_num;
+ uint16_t block_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ p_context = osm_madw_get_pkey_context_ptr( p_madw );
+ p_pkey_tbl = (ib_pkey_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+ port_guid = p_context->port_guid;
+ node_guid = p_context->node_guid;
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_process: ERR 4806: "
+ "No Port object for port with GUID = 0x%" PRIx64
+ "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ goto Exit;
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ block_num = (uint16_t)((cl_ntoh32(p_smp->attr_mod)) & 0x0000FFFF);
+ /* in case of a non switch node the attr modifier should be ignored */
+ if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+ {
+ port_num = (uint8_t)(((cl_ntoh32( p_smp->attr_mod)) & 0x00FF0000) >> 16 );
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ }
+ else
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ port_num = p_port->default_port_num;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to update
+ the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_rcv_process: "
+ "Got GetResp(PKey) block:%u port_num %u with GUID = 0x%" PRIx64
+ " for parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ block_num, port_num,
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ /*
+ Determine if we encountered a new Physical Port.
+ If so, Ignore it.
+ */
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_process: "
+ "Got invalid port number 0x%X.\n",
+ port_num );
+ }
+ goto Exit;
+ }
+
+ osm_dump_pkey_block( p_rcv->p_log,
+ port_guid, block_num,
+ port_num, p_pkey_tbl,
+ OSM_LOG_DEBUG );
+
+ osm_physp_set_pkey_tbl( p_rcv->p_log, p_rcv->p_subn,
+ p_physp, p_pkey_tbl, block_num);
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pkey_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pkey_rcv_process( ((osm_pkey_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_construct(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_destroy(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_ctrl_init(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rcv_ctrl_init );
+
+ osm_pkey_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PKEY,
+ __osm_pkey_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_ctrl_init: ERR 4901: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_physp_t.
+ * This object represents an Infiniband Port.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_construct(
+ IN osm_physp_t* const p_physp )
+{
+ cl_memclr( p_physp, sizeof(*p_physp) );
+ osm_dr_path_construct( &p_physp->dr_path );
+ cl_ptr_vector_construct( &p_physp->slvl_by_port );
+ osm_pkey_tbl_construct( &p_physp->pkeys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_destroy(
+ IN osm_physp_t* const p_physp )
+{
+ size_t num_slvl, i;
+
+ /* the physp might be un-initialized */
+ if (p_physp->port_guid)
+ {
+ /* free the SL2VL Tables */
+ num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port);
+ for (i = 0; i < num_slvl; i++)
+ cl_free(cl_ptr_vector_get(&p_physp->slvl_by_port, i));
+ cl_ptr_vector_destroy(&p_physp->slvl_by_port);
+
+ /* free the P_Key Tables */
+ osm_pkey_tbl_destroy( &p_physp->pkeys );
+
+ cl_memclr( p_physp, sizeof(*p_physp) );
+ osm_dr_path_construct( &p_physp->dr_path ); /* clear dr_path */
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_init(
+ IN osm_physp_t* const p_physp,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const struct _osm_node* const p_node,
+ IN const osm_bind_handle_t h_bind,
+ IN const uint8_t hop_count,
+ IN const uint8_t* const p_initial_path )
+{
+ uint16_t num_slvl, i;
+ ib_slvl_table_t *p_slvl;
+ CL_ASSERT( p_node );
+
+ osm_physp_construct( p_physp );
+ p_physp->port_guid = port_guid;
+ p_physp->port_num = port_num;
+ p_physp->healthy = TRUE;
+ p_physp->p_node = (struct _osm_node*)p_node;
+
+ osm_dr_path_init(
+ &p_physp->dr_path,
+ h_bind,
+ hop_count,
+ p_initial_path );
+
+ /* allocate enough SL2VL tables */
+ if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+ {
+ /* we need node num ports + 1 SL2VL tables */
+ num_slvl = osm_node_get_num_physp( p_node ) + 1;
+ }
+ else
+ {
+ /* An end node - we need only one SL2VL */
+ num_slvl = 1;
+ }
+
+ cl_ptr_vector_init( &p_physp->slvl_by_port, num_slvl, 1);
+ for (i = 0; i < num_slvl; i++)
+ {
+ p_slvl = (ib_slvl_table_t *)cl_zalloc(sizeof(ib_slvl_table_t));
+ cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl);
+ }
+
+ /* initialize the pkey table */
+ osm_pkey_tbl_init( &p_physp->pkeys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_destroy(
+ IN osm_port_t* const p_port )
+{
+ /* cleanup all mcm recs attached */
+ osm_port_remove_all_mgrp( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_init(
+ IN osm_port_t* const p_port,
+ IN const ib_node_info_t* p_ni,
+ IN const osm_node_t* const p_parent_node )
+{
+ uint32_t port_index;
+ ib_net64_t port_guid;
+ osm_physp_t *p_physp;
+ uint32_t size;
+
+ CL_ASSERT( p_port );
+ CL_ASSERT( p_ni );
+ CL_ASSERT( p_parent_node );
+
+ osm_port_construct( p_port );
+
+ p_port->p_node = (struct _osm_node *)p_parent_node;
+ port_guid = p_ni->port_guid;
+ p_port->guid = port_guid;
+
+ /*
+ See comment in port_new for info about this...
+ */
+ size = p_ni->num_ports;
+
+ p_port->physp_tbl_size = (uint8_t)(size + 1);
+
+ /*
+ Get the pointers to the physical node objects "owned" by this
+ logical port GUID.
+ For switches, all the ports are owned, for HCA's and routers,
+ only the singular part that has this GUID is owned.
+ */
+ p_port->default_port_num = 0xFF;
+ for( port_index = 0; port_index < p_port->physp_tbl_size; port_index++ )
+ {
+ p_physp = osm_node_get_physp_ptr( p_parent_node, port_index );
+ if( osm_physp_is_valid( p_physp ) &&
+ port_guid == osm_physp_get_port_guid( p_physp ) )
+ {
+ p_port->tbl[port_index] = p_physp;
+ /*
+ Because much of the PortInfo data is only valid
+ for port 0 on switches, try to keep the lowest
+ possible value of default_port_num.
+ */
+ if( port_index < p_port->default_port_num )
+ p_port->default_port_num = (uint8_t)port_index;
+ }
+ else
+ p_port->tbl[port_index] = NULL;
+ }
+
+ CL_ASSERT( p_port->default_port_num < 0xFF );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t*
+osm_port_new(
+ IN const ib_node_info_t* p_ni,
+ IN const osm_node_t* const p_parent_node )
+{
+ osm_port_t* p_port;
+ uint32_t size;
+
+ /*
+ The port object already contains one physical port object pointer.
+ Therefore, subtract 1 from the number of physical ports
+ used by the switch. This is not done for CA's since they
+ need to occupy 1 more physp pointer than they physically have since
+ we still reserve room for a "port 0".
+ */
+ size = p_ni->num_ports;
+
+ p_port = cl_zalloc( sizeof(*p_port) + sizeof(void *) * size );
+ if( p_port != NULL )
+ osm_port_init( p_port, p_ni, p_parent_node );
+
+ return( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_get_lid_range_ho(
+ IN const osm_port_t* const p_port,
+ IN uint16_t* const p_min_lid,
+ IN uint16_t* const p_max_lid )
+{
+ uint8_t lmc;
+
+ *p_min_lid = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+ lmc = osm_port_get_lmc( p_port );
+ *p_max_lid = (uint16_t)(*p_min_lid + (1 << lmc) - 1 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_add_new_physp(
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num )
+{
+ osm_node_t *p_node;
+ osm_physp_t *p_physp;
+
+ CL_ASSERT( port_num < p_port->physp_tbl_size );
+
+ p_node = p_port->p_node;
+ CL_ASSERT( p_node );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_physp_get_port_guid( p_physp ) == p_port->guid );
+ p_port->tbl[port_num] = p_physp;
+
+ /*
+ For switches, we generally want to use Port 0, which is
+ the management port as the default Physical Port.
+ The LID value in the PortInfo for example, is only valid
+ for port 0 on switches.
+ */
+ if( !osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) )
+ {
+ p_port->default_port_num = port_num;
+ }
+ else
+ {
+ if( port_num < p_port->default_port_num )
+ {
+ p_port->default_port_num = port_num;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_port_add_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_mcm_info_t *p_mcm;
+
+ p_mcm = osm_mcm_info_new( mlid );
+ if( p_mcm )
+ cl_qlist_insert_tail( &p_port->mcm_list, (cl_list_item_t*)p_mcm );
+ else
+ status = IB_INSUFFICIENT_MEMORY;
+
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static cl_status_t
+__osm_port_mgrp_find_func(
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ if( *((ib_net16_t*)context) == ((osm_mcm_info_t*)p_list_item)->mlid )
+ return( CL_SUCCESS );
+ else
+ return( CL_NOT_FOUND );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid )
+{
+ cl_list_item_t *p_mcm;
+
+ p_mcm = cl_qlist_find_from_head( &p_port->mcm_list,
+ __osm_port_mgrp_find_func, &mlid );
+
+ if( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+ {
+ cl_qlist_remove_item( &p_port->mcm_list, p_mcm );
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_all_mgrp(
+ IN osm_port_t* const p_port )
+{
+ cl_list_item_t *p_mcm;
+
+ p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+ while( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+ {
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_mtu(
+ IN osm_log_t* p_log,
+ IN const osm_physp_t* p_physp )
+{
+ const ib_port_info_t* p_old_pi;
+ const ib_port_info_t* p_remote_pi;
+ const osm_physp_t* p_remote_physp;
+ uint8_t mtu;
+ uint8_t remote_mtu;
+
+ OSM_LOG_ENTER( p_log, osm_physp_calc_link_mtu );
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /* use the available MTU */
+ mtu = ib_port_info_get_mtu_cap( p_old_pi );
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+ remote_mtu = ib_port_info_get_mtu_cap( p_remote_pi );
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_mtu: "
+ "Remote port 0x%016" PRIx64 " port# = 0x%X : "
+ "MTU = %u. This Port MTU: %u\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ),
+ remote_mtu, mtu );
+ }
+
+ if( mtu != remote_mtu )
+ {
+ if( mtu > remote_mtu )
+ mtu = remote_mtu;
+
+ if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "osm_physp_calc_link_mtu: "
+ "MTU mismatch between ports."
+ "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X"
+ " and port 0x%016" PRIx64 ", port# 0x%X."
+ "\n\t\t\t\tUsing lower MTU of %u.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ),
+ cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ),
+ mtu );
+ }
+ }
+ }
+
+ if( mtu == 0 )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_mtu: ERR 4101: "
+ "Invalid MTU = 0. Forcing correction to 256.\n" );
+ mtu = 1;
+ }
+
+ OSM_LOG_EXIT( p_log );
+ return(mtu);
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_op_vls(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t* p_subn,
+ IN const osm_physp_t* p_physp )
+{
+ const ib_port_info_t* p_old_pi;
+ const ib_port_info_t* p_remote_pi;
+ const osm_physp_t* p_remote_physp;
+ uint8_t op_vls;
+ uint8_t remote_op_vls;
+
+ OSM_LOG_ENTER( p_log, osm_physp_calc_link_op_vls );
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /* use the available VL CAP */
+ op_vls = ib_port_info_get_vl_cap(p_old_pi);
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+ remote_op_vls = ib_port_info_get_vl_cap(p_remote_pi);
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_op_vls: "
+ "Remote port 0x%016" PRIx64 " port# = 0x%X : "
+ "VL_CAP = %u. This port VL_CAP:%u\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ),
+ remote_op_vls,
+ op_vls
+ );
+ }
+
+ if( op_vls != remote_op_vls )
+ {
+ if( op_vls > remote_op_vls )
+ op_vls = remote_op_vls;
+
+ if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "osm_physp_calc_link_op_vls: "
+ "OP_VLS mismatch between ports."
+ "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X"
+ " and port 0x%016" PRIx64 ", port# 0x%X."
+ "\n\t\t\t\tUsing lower OP_VLS of %u.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ),
+ cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ),
+ op_vls );
+ }
+ }
+ }
+
+ /* support user limitation of max_op_vls */
+ if (op_vls > p_subn->opt.max_op_vls)
+ op_vls = p_subn->opt.max_op_vls;
+
+ if( op_vls == 0 )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_op_vls: ERR 4102: "
+ "Invalid OP_VLS = 0. Forcing correction to 256.\n" );
+ op_vls = 1;
+ }
+
+ OSM_LOG_EXIT( p_log );
+ return(op_vls);
+}
+
+inline
+uint64_t
+__osm_ptr_to_key(void const *p) {
+ uint64_t k = 0;
+ cl_memcpy(&k, p, sizeof(void *));
+ return k;
+}
+
+inline
+void *
+__osm_key_to_ptr(uint64_t k) {
+ void *p = 0;
+ cl_memcpy(&p, &k, sizeof(void *));
+ return p;
+}
+
+/**********************************************************************
+ Traverse the fabric from the SM node following the DR path given and
+ add every phys port traversed to the map. Avoid tracking the first and
+ last phys ports (going into the first switch and into the target port).
+ **********************************************************************/
+cl_status_t
+__osm_physp_get_dr_physp_set(
+ IN osm_log_t* p_log,
+ IN osm_subn_t const *p_subn,
+ IN osm_dr_path_t const *p_path,
+ OUT cl_map_t* p_physp_map)
+{
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ uint8_t hop;
+ cl_status_t status = CL_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, __osm_physp_get_dr_physp_set );
+
+ /* find the OSM node */
+ p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid);
+ if (! p_port)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_physp_get_dr_nodes_set: ERR 4103: "
+ "Fail to find the SM own port by guid.\n");
+ status = CL_ERROR;
+ goto Exit;
+ }
+
+ /* get the node of the SM */
+ p_node = osm_port_get_parent_node(p_port);
+
+ /*
+ traverse the path adding the nodes to the table
+ start after the first dummy hop and stop just before the
+ last one
+ */
+ for (hop = 1; hop < p_path->hop_count - 1; hop++)
+ {
+ /* go out using the phys port of the path */
+ p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
+
+ /* we track the ports we go out along the path */
+ if (hop > 1)
+ cl_map_insert(p_physp_map, __osm_ptr_to_key(p_physp), NULL);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__osm_physp_get_dr_nodes_set: "
+ "Traversed through node: 0x%016" PRIx64
+ " port:%u\n",
+ cl_ntoh64(p_node->node_info.node_guid),
+ p_path->path[hop]);
+
+ /* make sure we got a valid port and it has a remote port */
+ if (!(p_physp && osm_physp_is_valid( p_physp )))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_physp_get_dr_nodes_set: ERR 4104: "
+ "DR Traversal stopped on invalid port at hop:%u\n",
+ hop);
+ status = CL_ERROR;
+ goto Exit;
+ }
+
+ if (! (p_physp = osm_physp_get_remote(p_physp)))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_physp_get_dr_nodes_set: ERR 4106: "
+ "DR Traversal stopped on missing remote physp at hop:%u\n",
+ hop);
+ status = CL_ERROR;
+ goto Exit;
+ }
+
+ p_node = osm_physp_get_node_ptr(p_physp);
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_physp_update_new_dr_path(
+ IN osm_physp_t const *p_dest_physp,
+ IN cl_map_t *p_visited_map,
+ IN osm_bind_handle_t *h_bind )
+{
+ cl_list_t tmpPortsList;
+ osm_physp_t *p_physp, *p_src_physp = NULL;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+ uint8_t i = 0;
+ osm_dr_path_t *p_dr_path;
+
+ cl_list_construct( &tmpPortsList );
+ cl_list_init( &tmpPortsList, 10 );
+
+ cl_list_insert_head( &tmpPortsList, p_dest_physp );
+ /* get the output port where we need to come from */
+ p_physp = (osm_physp_t*)cl_map_get( p_visited_map,
+ __osm_ptr_to_key(p_dest_physp) );
+ while ( p_physp != NULL )
+ {
+ cl_list_insert_head( &tmpPortsList, p_physp );
+ /* get the input port through where we reached the output port */
+ p_src_physp = p_physp;
+ p_physp = (osm_physp_t*)cl_map_get( p_visited_map,
+ __osm_ptr_to_key(p_physp) );
+ /* if we reached a null p_physp - this means we are at the begining
+ of the path. Break. */
+ if ( p_physp == NULL )
+ break;
+ /* get the output port */
+ p_physp = (osm_physp_t*)cl_map_get( p_visited_map,
+ __osm_ptr_to_key(p_physp) );
+ }
+
+ cl_memclr( path_array, sizeof(path_array) );
+ p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList );
+ while ( p_physp != NULL )
+ {
+ i++;
+ path_array[i] = p_physp->port_num;
+ p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList );
+ }
+ if (p_src_physp)
+ {
+ p_dr_path = osm_physp_get_dr_path_ptr( p_src_physp );
+ osm_dr_path_init( p_dr_path, h_bind, i, path_array );
+ }
+
+ cl_list_destroy( &tmpPortsList );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_replace_dr_path_with_alternate_dr_path(
+ IN osm_log_t *p_log,
+ IN osm_subn_t const *p_subn,
+ IN osm_physp_t const *p_dest_physp,
+ IN osm_bind_handle_t *h_bind
+ )
+{
+ cl_map_t physp_map;
+ cl_map_t visited_map;
+ osm_dr_path_t * p_dr_path;
+ cl_list_t *p_currPortsList;
+ cl_list_t *p_nextPortsList;
+ cl_qmap_t const *p_port_tbl;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp, *p_remote_physp;
+ ib_net64_t port_guid;
+ boolean_t next_list_is_full = TRUE, reached_dest = FALSE;
+ uint8_t num_ports, port_num;
+
+ /*
+ initialize the map of all port participating in current dr path
+ not including first and last switches
+ */
+ cl_map_construct( &physp_map );
+ cl_map_init( &physp_map, 4 );
+ cl_map_construct( &visited_map );
+ cl_map_init( &visited_map, 4 );
+ p_dr_path = osm_physp_get_dr_path_ptr( p_dest_physp );
+ __osm_physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map);
+
+ /*
+ BFS from OSM port until we find the target physp but avoid
+ going through mapped ports
+ */
+ p_nextPortsList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextPortsList );
+ cl_list_init( p_nextPortsList, 10 );
+
+ p_port_tbl = &p_subn->port_guid_tbl;
+ port_guid = p_subn->sm_port_guid;
+
+ CL_ASSERT( port_guid );
+
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_replace_dr_path_with_alternate_dr_path: ERR 4105: "
+ "No SM port object.\n" );
+ goto Exit;
+ }
+
+ /*
+ HACK: We are assuming SM is running on HCA, so when getting the default
+ port we'll get the port connected to the rest of the subnet. If SM is
+ running on SWITCH - we should try to get a dr path from all switch ports.
+ */
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ cl_list_insert_tail( p_nextPortsList, p_physp );
+
+ while (next_list_is_full == TRUE)
+ {
+ next_list_is_full = FALSE;
+ p_currPortsList = p_nextPortsList;
+ p_nextPortsList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextPortsList );
+ cl_list_init( p_nextPortsList, 10 );
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+ while ( p_physp != NULL )
+ {
+ /* If we are in a switch - need to go out through all the other
+ physical ports of the switch */
+ num_ports = osm_node_get_num_physp( p_physp->p_node );
+
+ for (port_num = 1 ; port_num < num_ports ; port_num++)
+ {
+ if (osm_node_get_type( p_physp->p_node ) == IB_NODE_TYPE_SWITCH)
+ p_remote_physp = osm_node_get_physp_ptr( p_physp->p_node, port_num );
+ else
+ /* this is HCA or router - the remote port is just the port connected
+ on the other side */
+ p_remote_physp = p_physp->p_remote_physp;
+
+ /*
+ make sure that all three of the following occure:
+ 1. The port isn't NULL
+ 2. The port is a valid port
+ 3. This is not the port we came from
+ 4. The port is not in the physp_map
+ 5. This port haven't been visited before
+ */
+ if ( p_remote_physp &&
+ osm_physp_is_valid ( p_remote_physp ) &&
+ p_remote_physp != p_physp &&
+ cl_map_get( &physp_map, __osm_ptr_to_key(p_remote_physp)) == NULL &&
+ cl_map_get( &visited_map, __osm_ptr_to_key(p_remote_physp)) == NULL )
+ {
+ /* Insert the port into the visited_map, and save its source port */
+ cl_map_insert( &visited_map, __osm_ptr_to_key(p_remote_physp), p_physp );
+
+ /* Is this the p_dest_physp? */
+ if ( p_remote_physp == p_dest_physp )
+ {
+ /* update the new dr path */
+ __osm_physp_update_new_dr_path( p_dest_physp, &visited_map, h_bind );
+ reached_dest = TRUE;
+ break;
+ }
+
+ /* add the p_remote_physp to the nextPortsList */
+ cl_list_insert_tail( p_nextPortsList, p_remote_physp );
+ next_list_is_full = TRUE;
+ }
+ }
+
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+ if ( reached_dest == TRUE )
+ {
+ /* free the rest of the currPortsList */
+ while ( p_physp != NULL )
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+ /* free the nextPortsList, if items were added to it */
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList );
+ while ( p_physp != NULL )
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList );
+ next_list_is_full = FALSE;
+ }
+ }
+ cl_list_destroy( p_currPortsList );
+ cl_free(p_currPortsList);
+ }
+
+ /* cleanup */
+ Exit:
+ cl_list_destroy( p_nextPortsList );
+ cl_free( p_nextPortsList );
+ cl_map_destroy( &physp_map );
+ cl_map_destroy( &visited_map );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_link_is_healthy(
+ IN const osm_physp_t* const p_physp )
+{
+ osm_physp_t* p_remote_physp;
+ CL_ASSERT( p_physp );
+ p_remote_physp = p_physp->p_remote_physp;
+ if (p_remote_physp != NULL && osm_physp_is_valid(p_remote_physp) )
+ return( (p_physp->healthy)&(p_remote_physp->healthy) );
+ /* the other side is not known - consider the link as healthy */
+ return(TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_set_pkey_tbl(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t* p_subn,
+ IN osm_physp_t* const p_physp,
+ IN ib_pkey_table_t *p_pkey_tbl,
+ IN uint16_t block_num )
+{
+ uint16_t max_blocks;
+ osm_switch_t* p_switch;
+
+ CL_ASSERT( p_pkey_tbl );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ /*
+ (14.2.5.7) - the block number valid values are 0-2047, and are further
+ limited by the size of the P_Key table specified by the PartitionCap on the
+ node.
+ */
+ if (osm_node_get_type( p_physp->p_node ) != IB_NODE_TYPE_SWITCH ||
+ p_physp->port_num == 0 )
+ {
+ /*
+ The maximum blocks is defined in the node info: partition cap for CA,
+ routers and switch management ports.
+ */
+ max_blocks = (cl_ntoh16(p_physp->p_node->node_info.partition_cap)+
+ IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
+ / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+ }
+ else
+ {
+ /*
+ This is a switch, and not a management port. The maximum blocks is defined
+ in the switch info: partition enforcement cap.
+ */
+ p_switch =
+ osm_get_switch_by_guid(p_subn, p_physp->p_node->node_info.node_guid);
+ if (! p_switch)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_set_pkey_tbl: ERR 4107: "
+ "Cannot find switch by guid: %" PRIx64 "\n",
+ cl_ntoh64(p_physp->p_node->node_info.node_guid) );
+ return;
+ }
+
+ max_blocks =
+ (cl_ntoh16(p_switch->switch_info.enforce_cap) +
+ IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+ }
+
+ if ( block_num >= max_blocks )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_set_pkey_tbl: ERR 4108: "
+ "Got illegal set for block number:%u "
+ "For GUID: %" PRIx64 " port number:%u\n",
+ block_num,
+ cl_ntoh64(p_physp->p_node->node_info.node_guid),
+ p_physp->port_num );
+ return;
+ }
+
+ osm_pkey_tbl_set( &p_physp->pkeys, block_num, p_pkey_tbl);
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_port_info_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_set_sm(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp )
+{
+ osm_bind_handle_t h_bind;
+ osm_dr_path_t *p_dr_path;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_set_sm );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pi_rcv_set_sm: "
+ "Setting 'IS_SM' bit in port attributes.\n" );
+ }
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+ /*
+ The 'IS_SM' bit isn't already set, so set it.
+ */
+ osm_vendor_set_sm( h_bind, TRUE );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_endport(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ ib_net64_t port_guid;
+ uint8_t rate, mtu;
+ cl_qmap_t* p_sm_tbl;
+ osm_remote_sm_t* p_sm;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_endport );
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ /* HACK should we track extended port 0 too? */
+ if (osm_physp_get_port_num( p_physp ) != 0)
+ {
+ /* track the minimal endport MTU and rate */
+ mtu = ib_port_info_get_mtu_cap(p_pi);
+ if (mtu < p_rcv->p_subn->min_ca_mtu)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Setting endport minimal MTU to:%u defined by port:0x%"
+ PRIx64 ".\n",
+ mtu,
+ cl_ntoh64( port_guid ) );
+ p_rcv->p_subn->min_ca_mtu = mtu;
+ }
+
+ rate = ib_port_info_compute_rate( p_pi );
+ if (rate < p_rcv->p_subn->min_ca_rate)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Setting endport minimal rate to:%u defiend by port:0x%"
+ PRIx64 ".\n",
+ rate,
+ cl_ntoh64( port_guid ) );
+ p_rcv->p_subn->min_ca_rate = rate;
+ }
+ }
+
+ if( port_guid == p_rcv->p_subn->sm_port_guid )
+ {
+ /*
+ We received the PortInfo for our own port.
+ */
+ if( !(p_pi->capability_mask & IB_PORT_CAP_IS_SM ) )
+ {
+ /*
+ Set the IS_SM bit to indicate our port hosts an SM.
+ */
+ __osm_pi_rcv_set_sm( p_rcv, p_physp );
+ }
+ }
+ else
+ {
+ /*
+ Before querying the SM - we want to make sure we clean its state, so
+ if the querying fails we recognize that this SM is not active.
+ */
+ p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
+ p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid );
+ if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) )
+ {
+ /* clean it up */
+ p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state;
+ }
+
+ if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
+ {
+ if( p_rcv->p_subn->opt.ignore_other_sm )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Ignoring SM on port 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Detected another SM. Requesting SMInfo."
+ "\n\t\t\t\tPort 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ }
+
+ /*
+ This port indicates it's an SM, and it's not our own port.
+ Acquire the SMInfo Attribute.
+ */
+ cl_memclr( &context, sizeof(context) );
+ context.smi_context.set_method = FALSE;
+ status = osm_req_get( p_rcv->p_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_SM_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_endport: ERR 0F05: "
+ "Failure requesting SMInfo (%s).\n",
+ ib_get_err_str( status ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_pi_rcv_process_switch_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_remote_physp;
+ osm_node_t *p_remote_node;
+ uint8_t port_num;
+ uint8_t remote_port_num;
+ osm_dr_path_t path;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_switch_port );
+
+ /*
+ Check the state of the physical port.
+ If there appears to be something on the other end of the wire,
+ then ask for NodeInfo. Ignore the switch managment port.
+ */
+ port_num = osm_physp_get_port_num( p_physp );
+ /* if in_sweep_hop_0 is TRUE, then this means the SM in on the switch,
+ and we got switchInfo of our local switch. Do not continue
+ probing through the switch. */
+ if( port_num != 0 && p_rcv->p_subn->in_sweep_hop_0 == FALSE)
+ {
+ switch( ib_port_info_get_port_state( p_pi ) )
+ {
+ case IB_LINK_DOWN:
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+ remote_port_num = osm_physp_get_port_num( p_remote_physp );
+
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_switch_port: "
+ "Unlinking local node 0x%" PRIx64 ", port 0x%X"
+ "\n\t\t\t\tand remote node 0x%" PRIx64
+ ", port 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ remote_port_num );
+
+ osm_node_unlink( p_node, (uint8_t)port_num,
+ p_remote_node, (uint8_t)remote_port_num );
+
+ }
+ break;
+
+ case IB_LINK_INIT:
+ case IB_LINK_ARMED:
+ case IB_LINK_ACTIVE:
+ /*
+ To avoid looping forever, only probe the port if it
+ is NOT the port that responded to the SMP.
+
+ Request node info from the other end of this link:
+ 1) Copy the current path from the parent node.
+ 2) Extend the path to the next hop thru this port.
+ 3) Request node info with the new path
+
+ */
+ if( p_pi->local_port_num != osm_physp_get_port_num( p_physp ) )
+ {
+ path = *osm_physp_get_dr_path_ptr( p_physp );
+
+ osm_dr_path_extend( &path,
+ osm_physp_get_port_num( p_physp ) );
+
+ context.ni_context.node_guid =
+ osm_node_get_node_guid( p_node );
+ context.ni_context.port_num =
+ osm_physp_get_port_num( p_physp );
+
+ status = osm_req_get( p_rcv->p_req,
+ &path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_switch_port: ERR 0F02: "
+ "Failure initiating NodeInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pi_rcv_process_switch_port: "
+ "Skipping SMP responder port 0x%X.\n",
+ p_pi->local_port_num );
+ }
+ }
+ break;
+
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_switch_port: ERR 0F03: "
+ "Unknown link state = %u, port = 0x%X.\n",
+ osm_physp_get_port_state( p_physp ),
+ p_pi->local_port_num );
+ break;
+ }
+ }
+
+ /*
+ Update the PortInfo attribute.
+ */
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ if (port_num == 0)
+ {
+ /* This is a management port 0 */
+ __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_ca_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_ca_port );
+
+ UNUSED_PARAM( p_node );
+
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_router_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_router_port );
+
+ UNUSED_PARAM( p_node );
+
+ /*
+ Update the PortInfo attribute.
+ */
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_get_tables(
+ IN osm_log_t *p_log,
+ IN osm_req_t *p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp ) {
+
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ osm_dr_path_t path;
+ uint8_t port_num;
+ uint16_t block_num, max_blocks;
+ osm_switch_t* p_switch;
+
+ OSM_LOG_ENTER( p_log, osm_physp_has_pkey );
+
+ path = *osm_physp_get_dr_path_ptr( p_physp );
+
+ context.pkey_context.node_guid =
+ osm_node_get_node_guid( p_node );
+ context.pkey_context.port_guid =
+ osm_physp_get_port_guid( p_physp );
+ context.pkey_context.set_method = FALSE;
+
+ port_num = p_physp->port_num;
+
+ if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
+ port_num == 0 )
+ {
+ /* The maximum blocks is defined on the node info partition cap for CA, routers and
+ switch management ports. */
+ max_blocks = (cl_ntoh16(p_node->node_info.partition_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
+ / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+ }
+ else
+ {
+ /* This is a switch, and not a management port. The maximum blocks is defined
+ on the switch info partition enforcement cap. */
+ p_switch = osm_get_switch_by_guid(p_subn, p_node->node_info.node_guid);
+
+ if (! p_switch)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_has_pkey: ERR 4A02: "
+ "Cannot find switch by guid: %" PRIx64 "\n",
+ cl_ntoh64(p_node->node_info.node_guid) );
+ goto Exit;
+ }
+ max_blocks = (cl_ntoh16(p_switch->switch_info.enforce_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
+ / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+ }
+
+ for (block_num = 0 ; block_num < max_blocks ; block_num++)
+ {
+ status = osm_req_get( p_req,
+ &path,
+ IB_MAD_ATTR_P_KEY_TABLE,
+ cl_hton32(block_num | (port_num << 16) ),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_has_pkey: ERR 4A03: "
+ "Failure initiating PkeyTable request (%s).\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pi_rcv_get_pkey_slvl_vla_tables(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_get_pkey_slvl_vla_tables );
+
+ osm_pkey_get_tables( p_rcv->p_log, p_rcv->p_req, p_rcv->p_subn,
+ p_node, p_physp );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_construct(
+ IN osm_pi_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_destroy(
+ IN osm_pi_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_init(
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_pi_rcv_init );
+
+ osm_pi_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process_set(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num,
+ IN osm_madw_t* const p_madw )
+{
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ ib_net64_t port_guid;
+ ib_smp_t *p_smp;
+ ib_port_info_t *p_pi;
+ osm_pi_context_t *p_context;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process_set );
+
+ p_context = osm_madw_get_pi_context_ptr( p_madw );
+
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ /* check for error */
+ if (!p_context->ignore_errors && (cl_ntoh16(p_smp->status) & 0x7fff))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process_set: ERR 0F10: "
+ "Received Error Status for SetResp()\n");
+ osm_dump_port_info(
+ p_rcv->p_log,
+ osm_node_get_node_guid( p_node ),
+ port_guid,
+ port_num,
+ p_pi,
+ OSM_LOG_ERROR);
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pi_rcv_process_set: "
+ "Received logical SetResp() for GUID = 0x%" PRIx64
+ ", port num = %u"
+ "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
+ " TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ),
+ port_num,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ /* We got a PortInfoSetResp - set the got_set_resp flag to TRUE */
+ p_physp->got_set_resp = TRUE;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_port_info_t *p_pi;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_dr_path_t *p_dr_path;
+ osm_node_t *p_node;
+ osm_pi_context_t *p_context;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_context = osm_madw_get_pi_context_ptr( p_madw );
+ p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod );
+
+ port_guid = p_context->port_guid;
+ node_guid = p_context->node_guid;
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO );
+
+ osm_dump_port_info(
+ p_rcv->p_log, node_guid, port_guid, port_num, p_pi, OSM_LOG_DEBUG);
+
+ /*
+ we might get a response during a light sweep looking for a change in
+ the status of a remote port that did not respond in earlier sweeps.
+ So if the context of the Get was light_sweep - we do not need to
+ do anything with the response - just flag that we need a heavy sweep
+ */
+ if (p_context->light_sweep == TRUE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "Got light sweep response from remote port of parent node GUID = 0x%" PRIx64
+ " port = %u, Commencing heavy sweep.\n",
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( port_guid ) );
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ OSM_SIGNAL_CHANGE_DETECTED );
+ goto Exit;
+ }
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process: ERR 0F06: "
+ "No Port object for port with GUID = 0x%" PRIx64
+ "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ goto Exit;
+ }
+
+ /*
+ If we were setting the PortInfo, then receiving
+ this attribute was not part of sweeping the subent.
+ In this case, just update the PortInfo attribute.
+
+ In an unfortunate blunder, the IB spec defines the
+ return method for Set() as a GetResp(). Thus, we can't
+ use the method (what would have been SetResp()) to determine
+ our course of action. So, we have to carry this extra
+ boolean around to determine if we were doing Get() or Set().
+ */
+ if( p_context->set_method )
+ {
+ osm_pi_rcv_process_set( p_rcv, p_port, port_num, p_madw );
+ }
+ else
+ {
+ osm_port_discovery_count_inc( p_port );
+
+ /*
+ This PortInfo arrived because we did a Get() method,
+ most likely due to a subnet sweep in progress.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "Discovered port num %u with GUID = 0x%" PRIx64
+ " for parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ port_num,
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_physp );
+
+ /*
+ Determine if we encountered a new Physical Port.
+ If so, initialize the new Physical Port then
+ continue processing as normal.
+ */
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "Initializing port number 0x%X.\n",
+ port_num );
+ }
+
+ osm_physp_init( p_physp,
+ port_guid,
+ port_num,
+ p_node,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count,
+ p_smp->initial_path );
+
+ osm_port_add_new_physp( p_port, port_num );
+ }
+ else
+ {
+ /*
+ Update the directed route path to this port
+ in case the old path is no longer usable.
+ */
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ osm_dr_path_init( p_dr_path,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count, p_smp->initial_path );
+ }
+
+ osm_dump_port_info( p_rcv->p_log,
+ node_guid, port_guid, port_num, p_pi,
+ OSM_LOG_DEBUG );
+
+ /*
+ Check if the update_sm_base_lid in the context is on TRUE.
+ If it is - then update the master_sm_base_lid of the variable
+ in the subnet.
+ */
+ if (p_context->update_master_sm_base_lid == TRUE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "update_master_sm is TRUE. "
+ "Updating master_sm_base_lid to:%u\n",
+ p_pi->master_sm_base_lid );
+
+ p_rcv->p_subn->master_sm_base_lid = p_pi->master_sm_base_lid;
+ }
+
+ switch( osm_node_get_type( p_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ __osm_pi_rcv_process_ca_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ __osm_pi_rcv_process_router_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ __osm_pi_rcv_process_switch_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process: ERR 0F07: "
+ "Unknown node type %u with GUID = 0x%" PRIx64 ".\n",
+ osm_node_get_type( p_node ),
+ cl_ntoh64( node_guid ) );
+ break;
+ }
+
+ /*
+ Get the tables on the physp.
+ */
+ __osm_pi_rcv_get_pkey_slvl_vla_tables( p_rcv, p_node, p_physp );
+
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ Exit:
+ /*
+ Release the lock before jumping here!!
+ */
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pi_rcv_ctrl_t.
+ * This object represents the PortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pi_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pi_rcv_process( ((osm_pi_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_construct(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_destroy(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_ctrl_init(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl,
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pi_rcv_ctrl_init );
+
+ osm_pi_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PORT_INFO,
+ __osm_pi_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_ctrl_init: ERR 1001: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sm_t.
+ * This object represents the remote SM object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_remote_sm.h>
+#include <complib/cl_memory.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_construct(
+ IN osm_remote_sm_t* const p_sm )
+{
+ cl_memclr( p_sm, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_destroy(
+ IN osm_remote_sm_t* const p_sm )
+{
+ cl_memclr( p_sm, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_remote_sm_init(
+ IN osm_remote_sm_t* const p_sm,
+ IN const osm_port_t* const p_port,
+ IN const ib_sm_info_t* const p_smi )
+{
+ CL_ASSERT( p_sm );
+ CL_ASSERT( p_port );
+
+ osm_remote_sm_construct( p_sm );
+
+ p_sm->p_port = p_port;
+ p_sm->smi = *p_smi;
+ return( IB_SUCCESS );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_req_t.
+ * This object represents the generic attribute requester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+ Next available error code: 0x300
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_construct(
+ IN osm_req_t* const p_req )
+{
+ cl_memclr( p_req, sizeof(*p_req) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_destroy(
+ IN osm_req_t* const p_req )
+{
+ CL_ASSERT( p_req );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_init(
+ IN osm_req_t* const p_req,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN atomic32_t* const p_sm_trans_id )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_req_init );
+
+ osm_req_construct( p_req );
+ p_req->p_log = p_log;
+
+
+ p_req->p_pool = p_pool;
+ p_req->p_vl15 = p_vl15;
+ p_req->p_subn = p_subn;
+ p_req->p_sm_trans_id = p_sm_trans_id;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_get(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context )
+{
+ osm_madw_t *p_madw;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t tid;
+
+ OSM_LOG_ENTER( p_req->p_log, osm_req_get );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_path );
+ CL_ASSERT( attr_id );
+
+ /* do nothing if we are exiting ... */
+ if (osm_exit_flag) goto Exit;
+
+ /* p_context may be NULL. */
+
+ p_madw = osm_mad_pool_get(
+ p_req->p_pool,
+ p_path->h_bind,
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_req->p_log, OSM_LOG_ERROR,
+ "osm_req_get: ERR 1101: "
+ "Unable to acquire MAD.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+ if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_req->p_log, OSM_LOG_DEBUG,
+ "osm_req_get: "
+ "Getting %s (0x%X), modifier = 0x%X, TID = 0x%" PRIx64 ".\n",
+ ib_get_sm_attr_str( attr_id ),
+ cl_ntoh16( attr_id ),
+ cl_ntoh32( attr_mod ),
+ cl_ntoh64( tid ) );
+ }
+
+ ib_smp_init_new(
+ osm_madw_get_smp_ptr( p_madw ),
+ IB_MAD_METHOD_GET,
+ tid,
+ attr_id,
+ attr_mod,
+ p_path->hop_count,
+ p_req->p_subn->opt.m_key,
+ p_path->path,
+ IB_LID_PERMISSIVE,
+ IB_LID_PERMISSIVE );
+
+ p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
+ p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
+ p_madw->resp_expected = TRUE;
+ p_madw->fail_msg = err_msg;
+
+ /*
+ Fill in the mad wrapper context for the recipient.
+ In this case, the only thing the recipient needs is the
+ guid value.
+ */
+
+ if( p_context )
+ p_madw->context = *p_context;
+
+ osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_req->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_set(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint8_t* const p_payload,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context )
+{
+ osm_madw_t *p_madw;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t tid;
+
+ OSM_LOG_ENTER( p_req->p_log, osm_req_set );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_path );
+ CL_ASSERT( attr_id );
+ CL_ASSERT( p_payload );
+
+ /* do nothing if we are exiting ... */
+ if (osm_exit_flag) goto Exit;
+
+ /* p_context may be NULL. */
+
+ p_madw = osm_mad_pool_get(
+ p_req->p_pool,
+ p_path->h_bind,
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_req->p_log, OSM_LOG_ERROR,
+ "osm_req_set: ERR 1102: "
+ "Unable to acquire MAD.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+ if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_req->p_log, OSM_LOG_DEBUG,
+ "osm_req_set: "
+ "Setting %s (0x%X), modifier = 0x%X, TID = 0x%" PRIx64 ".\n",
+ ib_get_sm_attr_str( attr_id ),
+ cl_ntoh16( attr_id ),
+ cl_ntoh32( attr_mod ),
+ cl_ntoh64( tid ) );
+ }
+
+ ib_smp_init_new(
+ osm_madw_get_smp_ptr( p_madw ),
+ IB_MAD_METHOD_SET,
+ tid,
+ attr_id,
+ attr_mod,
+ p_path->hop_count,
+ p_req->p_subn->opt.m_key,
+ p_path->path,
+ IB_LID_PERMISSIVE,
+ IB_LID_PERMISSIVE );
+
+ p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
+ p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
+ p_madw->resp_expected = TRUE;
+ p_madw->fail_msg = err_msg;
+
+ /*
+ Fill in the mad wrapper context for the recipient.
+ In this case, the only thing the recipient needs is the
+ guid value.
+ */
+
+ if( p_context )
+ p_madw->context = *p_context;
+
+ cl_memcpy( osm_madw_get_smp_ptr( p_madw )->data,
+ p_payload, IB_SMP_DATA_SIZE );
+
+ osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_req->p_log );
+ return( status );
+}
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_req_ctrl_t.
+ * This object represents the request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x102
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_req_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_req_get( ((osm_req_ctrl_t*)context)->p_req,
+ (&((osm_attrib_req_t*)p_data)->path),
+ ((osm_attrib_req_t*)p_data)->attrib_id,
+ ((osm_attrib_req_t*)p_data)->attrib_mod,
+ ((osm_attrib_req_t*)p_data)->err_msg,
+ (&((osm_attrib_req_t*)p_data)->context) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_construct(
+ IN osm_req_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_destroy(
+ IN osm_req_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_ctrl_init(
+ IN osm_req_ctrl_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_req_ctrl_init );
+
+ osm_req_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_req = p_req;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_REQ,
+ __osm_req_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_req_ctrl_init: ERR 1202: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_resp_t.
+ * This object represents the generic attribute responder.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_construct(
+ IN osm_resp_t* const p_resp )
+{
+ cl_memclr( p_resp, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_destroy(
+ IN osm_resp_t* const p_resp )
+{
+ CL_ASSERT( p_resp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_init(
+ IN osm_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_resp_init );
+
+ osm_resp_construct( p_resp );
+
+ p_resp->p_log = p_log;
+ p_resp->p_pool = p_pool;
+ p_resp->p_vl15 = p_vl15;
+ p_resp->p_subn = p_subn;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_make_resp_smp(
+ IN const osm_resp_t* const p_resp,
+ IN const ib_smp_t* const p_src_smp,
+ IN const ib_net16_t status,
+ IN const uint8_t* const p_payload,
+ OUT ib_smp_t* const p_dest_smp )
+{
+ OSM_LOG_ENTER( p_resp->p_log, osm_resp_make_resp_smp );
+
+ CL_ASSERT( p_dest_smp );
+ CL_ASSERT( p_src_smp );
+ CL_ASSERT( !ib_smp_is_response( p_src_smp ) );
+
+ *p_dest_smp = *p_src_smp;
+ if (p_src_smp->method == IB_MAD_METHOD_GET ||
+ p_src_smp->method == IB_MAD_METHOD_SET ) {
+ p_dest_smp->method = IB_MAD_METHOD_GET_RESP;
+ p_dest_smp->status = (ib_net16_t)(status | IB_SMP_DIRECTION);
+ } else if (p_src_smp->method == IB_MAD_METHOD_TRAP) {
+ p_dest_smp->method = IB_MAD_METHOD_TRAP_REPRESS;
+ p_dest_smp->status = 0;
+ }
+ else
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_resp_make_resp_smp: ERR 1302: "
+ "src smp method unsupported 0x%X.\n",
+ p_src_smp->method );
+ goto Exit;
+ }
+
+ p_dest_smp->dr_dlid = p_dest_smp->dr_slid;
+ p_dest_smp->dr_slid = p_dest_smp->dr_dlid;
+ cl_memcpy( &p_dest_smp->data, p_payload, IB_SMP_DATA_SIZE );
+
+ Exit:
+ OSM_LOG_EXIT( p_resp->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_send(
+ IN const osm_resp_t* const p_resp,
+ IN const osm_madw_t* const p_req_madw,
+ IN const ib_net16_t mad_status,
+ IN const uint8_t* const p_payload )
+{
+ const ib_smp_t* p_req_smp;
+ ib_smp_t* p_smp;
+ osm_madw_t* p_madw;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_resp->p_log, osm_resp_send );
+
+ CL_ASSERT( p_req_madw );
+ CL_ASSERT( p_payload );
+
+ /* do nothing if we are exiting ... */
+ if (osm_exit_flag) goto Exit;
+
+ p_madw = osm_mad_pool_get(
+ p_resp->p_pool,
+ osm_madw_get_bind_handle( p_req_madw ),
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_resp_send: ERR 1301: "
+ "Unable to acquire MAD.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ /*
+ Copy the requester smp to the response smp, then just
+ update the necessary fields.
+ */
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_req_smp = osm_madw_get_smp_ptr( p_req_madw );
+ osm_resp_make_resp_smp( p_resp, p_req_smp, mad_status,
+ p_payload, p_smp );
+ p_madw->mad_addr.dest_lid =
+ p_req_madw->mad_addr.addr_type.smi.source_lid;
+ p_madw->mad_addr.addr_type.smi.source_lid =
+ p_req_madw->mad_addr.dest_lid;
+
+ p_madw->resp_expected = FALSE;
+ p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+ if( osm_log_is_active( p_resp->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+ "osm_resp_send: "
+ "Responding to %s (0x%X)"
+ "\n\t\t\t\tattribute modifier = 0x%X, TID = 0x%" PRIx64 ".\n",
+ ib_get_sm_attr_str( p_smp->attr_id ),
+ cl_ntoh16( p_smp->attr_id ),
+ cl_ntoh32( p_smp->attr_mod ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ osm_vl15_post( p_resp->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_resp->p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_t.
+ * This object represents the Subnet Administrator object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+
+#define OSM_SA_INITIAL_TID_VALUE 0xabc
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_construct(
+ IN osm_sa_t* const p_sa )
+{
+ cl_memclr( p_sa, sizeof(*p_sa) );
+ p_sa->state = OSM_SA_STATE_INIT;
+ p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE;
+
+ osm_sa_mad_ctrl_construct( &p_sa->mad_ctrl );
+ osm_sa_resp_construct( &p_sa->resp );
+
+ osm_nr_rcv_construct( &p_sa->nr_rcv);
+ osm_nr_rcv_ctrl_construct( &p_sa->nr_rcv_ctrl );
+
+ osm_pir_rcv_construct( &p_sa->pir_rcv );
+ osm_pir_rcv_ctrl_construct( &p_sa->pir_rcv_ctrl );
+
+ osm_lr_rcv_construct( &p_sa->lr_rcv );
+ osm_lr_rcv_ctrl_construct( &p_sa->lr_rcv_ctrl );
+
+ osm_pr_rcv_construct( &p_sa->pr_rcv );
+ osm_pr_rcv_ctrl_construct( &p_sa->pr_rcv_ctrl );
+
+ osm_smir_rcv_construct( &p_sa->smir_rcv );
+ osm_smir_ctrl_construct( &p_sa->smir_ctrl );
+
+ osm_mcmr_rcv_construct(&p_sa->mcmr_rcv );
+ osm_mcmr_rcv_ctrl_construct(&p_sa->mcmr_rcv_ctlr);
+
+ osm_sr_rcv_construct( &p_sa->sr_rcv );
+ osm_sr_rcv_ctrl_construct( &p_sa->sr_rcv_ctrl );
+
+ osm_infr_rcv_construct( &p_sa->infr_rcv );
+ osm_infr_rcv_ctrl_construct( &p_sa->infr_rcv_ctrl );
+
+ osm_vlarb_rec_rcv_construct( &p_sa->vlarb_rec_rcv );
+ osm_vlarb_rec_rcv_ctrl_construct( &p_sa->vlarb_rec_rcv_ctrl );
+
+ osm_slvl_rec_rcv_construct( &p_sa->slvl_rec_rcv );
+ osm_slvl_rec_rcv_ctrl_construct( &p_sa->slvl_rec_rcv_ctrl );
+
+ osm_pkey_rec_rcv_construct( &p_sa->pkey_rec_rcv );
+ osm_pkey_rec_rcv_ctrl_construct( &p_sa->pkey_rec_rcv_ctrl );
+
+ osm_lftr_rcv_construct( &p_sa->lftr_rcv );
+ osm_lftr_rcv_ctrl_construct( &p_sa->lftr_rcv_ctrl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_shutdown(
+ IN osm_sa_t* const p_sa )
+{
+ ib_api_status_t status;
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_shutdown );
+
+ /* unbind from the mad service */
+ status = osm_sa_mad_ctrl_unbind( &p_sa->mad_ctrl );
+
+ /* remove any registered dispatcher message */
+ osm_nr_rcv_ctrl_destroy( &p_sa->nr_rcv_ctrl );
+ osm_pir_rcv_ctrl_destroy( &p_sa->pir_rcv_ctrl );
+ osm_lr_rcv_ctrl_destroy( &p_sa->lr_rcv_ctrl );
+ osm_pr_rcv_ctrl_destroy( &p_sa->pr_rcv_ctrl );
+ osm_smir_ctrl_destroy( &p_sa->smir_ctrl );
+ osm_mcmr_rcv_ctrl_destroy( &p_sa->mcmr_rcv_ctlr);
+ osm_sr_rcv_ctrl_destroy( &p_sa->sr_rcv_ctrl );
+ osm_infr_rcv_ctrl_destroy( &p_sa->infr_rcv_ctrl );
+ osm_vlarb_rec_rcv_ctrl_destroy( &p_sa->vlarb_rec_rcv_ctrl );
+ osm_slvl_rec_rcv_ctrl_destroy( &p_sa->slvl_rec_rcv_ctrl );
+ osm_pkey_rec_rcv_ctrl_destroy( &p_sa->pkey_rec_rcv_ctrl );
+ osm_lftr_rcv_ctrl_destroy( &p_sa->lftr_rcv_ctrl );
+ osm_sa_mad_ctrl_destroy( &p_sa->mad_ctrl );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_destroy(
+ IN osm_sa_t* const p_sa )
+{
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_destroy );
+
+ p_sa->state = OSM_SA_STATE_INIT;
+
+ osm_nr_rcv_destroy( &p_sa->nr_rcv );
+ osm_pir_rcv_destroy( &p_sa->pir_rcv );
+ osm_lr_rcv_destroy( &p_sa->lr_rcv );
+ osm_pr_rcv_destroy( &p_sa->pr_rcv );
+ osm_smir_rcv_destroy( &p_sa->smir_rcv );
+ osm_mcmr_rcv_destroy(&p_sa->mcmr_rcv);
+ osm_sr_rcv_destroy( &p_sa->sr_rcv );
+ osm_infr_rcv_destroy( &p_sa->infr_rcv );
+ osm_vlarb_rec_rcv_destroy( &p_sa->vlarb_rec_rcv );
+ osm_slvl_rec_rcv_destroy( &p_sa->slvl_rec_rcv );
+ osm_pkey_rec_rcv_destroy( &p_sa->pkey_rec_rcv );
+ osm_lftr_rcv_destroy( &p_sa->lftr_rcv );
+ osm_sa_resp_destroy( &p_sa->resp );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_init(
+ IN osm_sm_t* const p_sm,
+ IN osm_sa_t* const p_sa,
+ IN osm_subn_t* const p_subn,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_init );
+
+ p_sa->p_subn = p_subn;
+ p_sa->p_vendor = p_vendor;
+ p_sa->p_mad_pool = p_mad_pool;
+ p_sa->p_log = p_log;
+ p_sa->p_disp = p_disp;
+ p_sa->p_lock = p_lock;
+
+ p_sa->state = OSM_SA_STATE_READY;
+
+ status = osm_sa_resp_init(&p_sa->resp,
+ p_sa->p_mad_pool,
+ p_log);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+
+
+ status = osm_sa_mad_ctrl_init(
+ &p_sa->mad_ctrl,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_sa->p_vendor,
+ p_subn,
+ p_log,
+ p_stats,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_cpi_rcv_init(
+ &p_sa->cpi_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_cpi_rcv_ctrl_init(
+ &p_sa->cpi_rcv_ctrl,
+ &p_sa->cpi_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nr_rcv_init(
+ &p_sa->nr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nr_rcv_ctrl_init(
+ &p_sa->nr_rcv_ctrl,
+ &p_sa->nr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pir_rcv_init(
+ &p_sa->pir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pir_rcv_ctrl_init(
+ &p_sa->pir_rcv_ctrl,
+ &p_sa->pir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lr_rcv_init(
+ &p_sa->lr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lr_rcv_ctrl_init(
+ &p_sa->lr_rcv_ctrl,
+ &p_sa->lr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pr_rcv_init(
+ &p_sa->pr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pr_rcv_ctrl_init(
+ &p_sa->pr_rcv_ctrl,
+ &p_sa->pr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_smir_rcv_init(
+ &p_sa->smir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_stats,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_smir_ctrl_init(
+ &p_sa->smir_ctrl,
+ &p_sa->smir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcmr_rcv_init(
+ p_sm,
+ &p_sa->mcmr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcmr_rcv_ctrl_init(
+ &p_sa->mcmr_rcv_ctlr,
+ &p_sa->mcmr_rcv,
+ p_log,
+ p_disp);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sr_rcv_init(
+ &p_sa->sr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sr_rcv_ctrl_init(
+ &p_sa->sr_rcv_ctrl,
+ &p_sa->sr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_infr_rcv_init(
+ &p_sa->infr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_infr_rcv_ctrl_init(
+ &p_sa->infr_rcv_ctrl,
+ &p_sa->infr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vlarb_rec_rcv_init(
+ &p_sa->vlarb_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vlarb_rec_rcv_ctrl_init(
+ &p_sa->vlarb_rec_rcv_ctrl,
+ &p_sa->vlarb_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rec_rcv_init(
+ &p_sa->slvl_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rec_rcv_ctrl_init(
+ &p_sa->slvl_rec_rcv_ctrl,
+ &p_sa->slvl_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rec_rcv_init(
+ &p_sa->pkey_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rec_rcv_ctrl_init(
+ &p_sa->pkey_rec_rcv_ctrl,
+ &p_sa->pkey_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lftr_rcv_init(
+ &p_sa->lftr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lftr_rcv_ctrl_init(
+ &p_sa->lftr_rcv_ctrl,
+ &p_sa->lftr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_bind(
+ IN osm_sa_t* const p_sa,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_bind );
+
+ status = osm_sa_mad_ctrl_bind(
+ &p_sa->mad_ctrl, port_guid );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_gid_t osm_ipoib_mgid = {
+ {
+ 0xff, /* multicast field */
+ 0x12, /* non-permanent bit,scope */
+ 0x40, 0x1b, /* IPv4 signature */
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+ 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */
+ },
+};
+
+/*
+ * HACK: Until TS resolves their un-compliant join compmask
+ * we have to pre-define the MGID
+ */
+ib_gid_t osm_ts_ipoib_mgid = {
+ {
+ 0xff, /* multicast field */
+ 0x12, /* non-permanent bit,scope */
+ 0x40, 0x1b, /* IPv4 signature */
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+ 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */
+ },
+};
+
+void
+osm_sa_create_template_record_ipoib(
+ IN osm_sa_t* const p_sa,
+ IN const osm_subn_opt_t* const p_opt )
+{
+ ib_member_rec_t mc_rec;
+
+ osm_log( p_sa->p_log, OSM_LOG_FUNCS,
+ "osm_sa_create_template_record_ipoib: [\n" );
+
+ UNUSED_PARAM( p_opt );
+ cl_memclr(&mc_rec, sizeof(mc_rec));
+
+ /*
+ * Fill in the default MC Member record
+ */
+ mc_rec.mgid = osm_ipoib_mgid;
+ mc_rec.mtu = 4; /* 2048 Bytes */
+ mc_rec.qkey = CL_HTON32(0x0b1b); /* This value is pushed into the mad, and thus needs
+ to be in network order */
+ mc_rec.pkey = IB_DEFAULT_PKEY;
+ mc_rec.rate = 0x3; /* 10Gb/sec */
+ mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+ mc_rec.sl_flow_hop = OSM_DEFAULT_SL << 28;
+ /* Note: scope needs to be consistent with MGID */
+ mc_rec.scope_state = 0x21;
+
+ osm_sa_add_well_known_mc_record(&p_sa->mcmr_rcv, &mc_rec);
+
+ /*
+ * HACK: Until TS resolves their noncompliant join compmask
+ * we have to pre-define the MGID
+ */
+
+ mc_rec.mgid = osm_ts_ipoib_mgid;
+ osm_sa_add_well_known_mc_record(&p_sa->mcmr_rcv, &mc_rec);
+
+ osm_log( p_sa->p_log, OSM_LOG_FUNCS,
+ "osm_sa_create_template_record_ipoib: ]\n" );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_sa_add_well_known_mc_record(
+ osm_mcmr_recv_t* const p_mcmr,
+ const ib_member_rec_t * const p_well_know_mc_rec)
+{
+
+ osm_mgrp_t * p_mgrp = NULL;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+
+ comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE;
+ status = osm_mcmr_rcv_create_new_mgrp(
+ p_mcmr,
+ comp_mask,
+ p_well_know_mc_rec,
+ &p_mgrp);
+ if(p_mgrp)
+ {
+ p_mgrp->well_known = TRUE;
+ }
+ else
+ {
+ osm_log( p_mcmr->p_log, OSM_LOG_DEBUG,
+ "osm_sa_add_well_known_mc_record:"
+ "failed to create a well known group\n");
+
+ }
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_class_port_info.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_construct(
+ IN osm_cpi_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_destroy(
+ IN osm_cpi_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_destroy );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_init(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_cpi_rcv_init );
+
+ osm_cpi_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_cpi_rcv_respond(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw)
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_class_port_info_t *p_resp_cpi;
+ ib_api_status_t status;
+ ib_gid_t zero_gid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_cpi_rcv_respond );
+
+ cl_memclr(&zero_gid,sizeof(ib_gid_t));
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ MAD_BLOCK_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_cpi_rcv_respond: ERR 1408: "
+ "Unable to allocate MAD.\n" );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ p_resp_sa_mad->paylen_newwin = 0;
+
+ p_resp_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ /* finally do it (the job) man ! */
+ p_resp_cpi->base_ver = 1;
+ p_resp_cpi->class_ver = 2;
+ p_resp_cpi->resp_time_val = p_rcv->p_subn->opt.transaction_timeout;
+ p_resp_cpi->redir_gid = zero_gid;
+ p_resp_cpi->redir_tc_sl_fl = 0;
+ p_resp_cpi->redir_lid = 0;
+ p_resp_cpi->redir_pkey = 0;
+ p_resp_cpi->redir_qp = CL_NTOH32(1);
+ p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+ p_resp_cpi->trap_gid = zero_gid;
+ p_resp_cpi->trap_tc_sl_fl = 0;
+ p_resp_cpi->trap_lid = 0;
+ p_resp_cpi->trap_pkey = 0;
+ p_resp_cpi->trap_hop_qp = 0;
+ p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+
+ /* set specific capability mask bits */
+ /* we do not support the optionals:
+ OSM_CAP_IS_SUBN_OPT_RECS_SUP :
+ SwitchInfoRecord,
+ LinearForwardingTableRecord, (we do support it - under the table)
+ RandomForwardingTableRecord,
+ MulticastForwardingTableRecord,
+ SMInfoRecord, (we do support it - under the table)
+ InformInfoRecord,
+ LinkRecord, (we do support it - under the table)
+ GuidInfoRecord
+ ServiceAssociationRecord
+
+ OSM_CAP_IS_SUBN_OPT_MULTI_PATH_SUP:
+ MultiPathRecord,
+ TraceRecord
+
+ OSM_CAP_IS_SUBN_OPT_REINIT_SUP:
+ For re-initialization functionality.
+
+ So not sending traps, but supporting Get(Notice) and Set(Notice):
+ */
+ p_resp_cpi->cap_mask = 0x2; /* Note host notation replaced later */
+ if (p_rcv->p_subn->opt.no_multicast_option != TRUE)
+ p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP;
+
+ p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask);
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_cpi_rcv_respond: ERR 1409: "
+ "Unable to send MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ * This code actually handles the call
+ **********************************************************************/
+void
+osm_cpi_rcv_process(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /* we only supports GET */
+ if (p_sa_mad->method != IB_MAD_METHOD_GET)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_cpi_rcv_process: ERR 1403: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO );
+
+ /*
+ CLASS PORT INFO does not really look on the SMDB - no lock required.
+ */
+
+ __osm_cpi_rcv_respond( p_rcv, p_madw);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the ClassPortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_cpi_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_cpi_rcv_process( ((osm_cpi_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_construct(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_destroy(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_ctrl_init(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_cpi_rcv_ctrl_init );
+
+ osm_cpi_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_CLASS_PORT_INFO,
+ __osm_cpi_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_cpi_rcv_ctrl_init: ERR 1501: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_infr_rcv_t.
+ * This object represents the InformInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_pkey.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_construct(
+ IN osm_infr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_destroy(
+ IN osm_infr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_init(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_ERROR;
+
+ OSM_LOG_ENTER( p_log, osm_infr_rcv_init );
+
+ osm_infr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = IB_SUCCESS;
+ /* Exit: */
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+o13-14.1.1: Except for Set(InformInfo) requests with Inform-
+Info:LIDRangeBegin=0xFFFF, managers that support event forwarding
+shall, upon receiving a Set(InformInfo), verify that the requester originating
+the Set(InformInfo) and a Trap() source identified by Inform-
+can acess each other - can use path record to verify that.
+**********************************************************************/
+static
+boolean_t
+__validate_ports_access_rights(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_infr_t* p_infr_rec)
+{
+ boolean_t valid = TRUE;
+ osm_physp_t* p_requestor_physp;
+ osm_port_t* p_port;
+ osm_physp_t* p_physp;
+ ib_net64_t portguid;
+ ib_net16_t lid_range_begin;
+ ib_net16_t lid_range_end;
+ ib_net16_t lid;
+ const cl_ptr_vector_t* p_tbl;
+
+ ib_gid_t zero_gid;
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_ports_access_rights );
+
+ /* get the requestor physp from the request address */
+ p_requestor_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ &p_infr_rec->report_addr );
+
+ cl_memclr( &zero_gid, sizeof(zero_gid) );
+ if ( cl_memcmp (&(p_infr_rec->inform_record.inform_info.gid),
+ &zero_gid, sizeof(ib_gid_t) ) )
+ {
+ /* a gid is defined */
+ portguid = p_infr_rec->inform_record.inform_info.gid.unicast.interface_id;
+
+ p_port = osm_get_port_by_guid( p_rcv->p_subn, portguid );
+
+ if ( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_ports_access_rights: ERR 4301: "
+ "Invalid port guid: 0x%016 \n",
+ portguid );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /* get the destination informInfo physical port */
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+
+ /* make sure that the requestor and destination port can access each other
+ according to the current partitioning. */
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requestor_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_ports_access_rights: "
+ "port and requestor don't share pkey. \n" );
+ valid = FALSE;
+ goto Exit;
+ }
+ } else {
+ /* gid is zero - check if LID range is defined */
+ lid_range_begin = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_begin);
+ /* if lid is 0xFFFF - meaning all endports managed by the manager */
+ if ( lid_range_begin == 0xFFFF )
+ goto Exit;
+
+ lid_range_end = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_end);
+
+ /* lid_range_end is set to zero if no range desired. In this case -
+ just make it equal to the lid_range_begin. */
+ if (lid_range_end == 0)
+ lid_range_end = lid_range_begin;
+
+ /* go over all defined lids within the range and make sure that the
+ requestor port can access them according to current partitioning. */
+ for ( lid = lid_range_begin ; lid <= lid_range_end ; lid++ )
+ {
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ if ( cl_ptr_vector_get_size(p_tbl) > lid )
+ {
+ p_port = cl_ptr_vector_get (p_tbl, lid );
+ }
+ else
+ {
+ /* lid requested is out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_ports_access_rights: ERR 4302: "
+ "Given LID (%u) is out of range:%u. \n",
+ lid, cl_ptr_vector_get_size(p_tbl) );
+ valid = FALSE;
+ goto Exit;
+ }
+ if (p_port == NULL )
+ continue;
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* make sure that the requestor and destination port can access each other
+ according to the current partitioning. */
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requestor_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_ports_access_rights: "
+ "port and requestor don't share pkey. \n" );
+ valid = FALSE;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static
+boolean_t
+__validate_infr(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_infr_t* p_infr_rec )
+{
+ boolean_t valid = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_infr );
+
+
+ valid = __validate_ports_access_rights( p_rcv, p_infr_rec);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_infr: "
+ "Invalid Access for InformInfo.\n");
+ valid = FALSE;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return valid;
+
+}
+
+/**********************************************************************
+o13-12.1.1: Confirm a valid request for event subscription by responding
+with an InformInfo attribute that is a copy of the data in the
+Set(InformInfo) request, but with InformInfo:Subscribe set to 1.
+**********************************************************************/
+static void
+__osm_infr_rcv_respond(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw)
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_inform_info_t* p_resp_infr;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_infr_rcv_respond );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_infr_rcv_respond: "
+ "Generating successful InformInfo response.\n");
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ MAD_BLOCK_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_infr_rcv_respond: ERR 4303: "
+ "Unable to allocate MAD.\n" );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /* copy the request InformInfo */
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, MAD_BLOCK_SIZE );
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ p_resp_sa_mad->paylen_newwin =
+ cl_hton32( sizeof(ib_inform_info_record_t) );
+
+ p_resp_infr = (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ /* confirm success */
+ p_resp_infr->subscribe = 1;
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_infr_rcv_respond: ERR 4304: "
+ "Unable to send MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+Recived an Set(InformInfo) MAD
+**********************************************************************/
+static
+void
+osm_infr_rcv_process_set_method(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_inform_info_t* p_recvd_inform_info;
+ osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */
+ osm_infr_t *p_infr;
+ uint8_t subscribe;
+ ib_net32_t qpn;
+ uint8_t resp_time_val;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_set_method );
+
+ CL_ASSERT( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_inform_info =
+ (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ /* the dump routine is not defined yet
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_inform_info_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ OSM_LOG_DEBUG );
+ }
+ */
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ /* define the inform record */
+ inform_info_rec.inform_record.inform_info = *p_recvd_inform_info;
+
+ /* following C13-32.1.2 Tbl 107 : we only copy the source address vector */
+ inform_info_rec.report_addr = p_madw->mad_addr;
+
+ /* we will need to know the mad srvc to send back through */
+ inform_info_rec.h_bind = p_madw->h_bind;
+ inform_info_rec.p_infr_rcv = p_rcv;
+
+ /* HACK: enum is always 0 */
+ inform_info_rec.inform_record.subscriber_enum = 0;
+
+ /* update the subscriber GID according to mad address */
+ inform_info_rec.inform_record.subscriber_gid =
+ osm_get_gid_by_mad_addr( p_rcv->p_log, p_rcv->p_subn, &p_madw->mad_addr );
+
+ /*
+ * MODIFICATIONS DONE ON INCOMING REQUEST:
+ *
+ * QPN:
+ * internally we keep the QPN field of the InformInfo updated
+ * so we can compare simply the entire record - when finding such.
+ * The Spec only require to fill the QPN field when an un-subscribe
+ * Set(InformInfo) is done. See table 106 p 654 QPN field
+ *
+ * SUBSCRIBE:
+ * For similar reasons we change the subscribe to 0 on the
+ * inserted/searched data
+ */
+
+ subscribe = p_recvd_inform_info->subscribe;
+ if (subscribe)
+ {
+ inform_info_rec.inform_record.inform_info.subscribe = 0;
+ ib_inform_info_set_qpn(
+ &inform_info_rec.inform_record.inform_info,
+ inform_info_rec.report_addr.addr_type.gsi.remote_qp);
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_set_method: "
+ "Got Subscribe Request with QPN: 0x%06X.\n",
+ cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.remote_qp)
+ );
+ }
+ else
+ {
+ ib_inform_info_get_qpn_resp_time(
+ p_recvd_inform_info->g_or_v.generic.qpn_resp_time_val,
+ &qpn, &resp_time_val);
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_set_method: "
+ "Got UnSubscribe Request with QPN: 0x%06X.\n",
+ cl_ntoh32(qpn)
+ );
+ }
+
+ /* If Record exist with matching InformInfo */
+ p_infr = osm_infr_get_by_rec(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ &inform_info_rec);
+
+ /* check to see if the request was for subscribe = 1 */
+ if (subscribe)
+ {
+
+ /* validate the request for a new or update InformInfo */
+ if (__validate_infr(p_rcv, &inform_info_rec) != TRUE)
+ {
+ cl_plock_release(p_rcv->p_lock);
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: ERR 4305: "
+ "Fail to validate a new inform object.\n");
+
+ /* o13-13.1.1: we need to set the subscribe bit to 0 */
+ p_recvd_inform_info->subscribe = 0;
+ osm_sa_send_error(
+ p_rcv->p_resp,
+ p_madw,
+ IB_SA_MAD_STATUS_REQ_INVALID);
+
+ goto Exit;
+ }
+
+ /* ok - we can try and create a new entry */
+ if(p_infr == NULL)
+ {
+ /* Create the instance of the osm_infr_t object */
+ p_infr = osm_infr_new(&inform_info_rec);
+ if(p_infr == NULL)
+ {
+ cl_plock_release(p_rcv->p_lock);
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: ERR 4306: "
+ "Fail to create a new inform object.\n");
+
+ /* o13-13.1.1: we need to set the subscribe bit to 0 */
+ p_recvd_inform_info->subscribe = 0;
+ osm_sa_send_error(
+ p_rcv->p_resp,
+ p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES);
+
+
+ goto Exit;
+ }
+
+ /* Add this new osm_infr_t object to subnet object */
+ osm_infr_insert_to_db(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_infr);
+
+ }
+ else
+ {
+ /* Update the old instance of the osm_infr_t object */
+ p_infr->inform_record = inform_info_rec.inform_record;
+ }
+ }
+ else
+ {
+ /* We got an Un-Subscribe request */
+ if(p_infr == NULL)
+ {
+ cl_plock_release(p_rcv->p_lock);
+
+ /* No Such Item - So Error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: ERR 4307: "
+ "Fail to Un-Subscribe to non exiting inform object.\n");
+
+ /* o13-13.1.1: we need to set the subscribe bit to 0 */
+ p_recvd_inform_info->subscribe = 0;
+ osm_sa_send_error(
+ p_rcv->p_resp,
+ p_madw,
+ IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+ else
+ {
+ /* Delete this object from the subnet list of informs */
+ osm_infr_remove_from_db(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_infr);
+ }
+ }
+
+ cl_plock_release(p_rcv->p_lock);
+
+ /* send the success response */
+ __osm_infr_rcv_respond(p_rcv, p_madw);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+void
+osm_infr_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+ CL_ASSERT( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ switch (p_sa_mad->method)
+ {
+ case IB_MAD_METHOD_SET:
+ osm_infr_rcv_process_set_method(p_rcv, p_madw);
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process: "
+ "Bad Method (%s)\n", ib_get_sa_method_str( p_sa_mad->method ));
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ break;
+ }
+
+ /* Exit: */
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_infr_rcv_ctrl_t.
+ * This object represents the InformInfo set request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_infr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_infr_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_construct(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_destroy(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_ctrl_init(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl,
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_infr_rcv_ctrl_init );
+
+ osm_infr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_INFORM_INFO,
+ __osm_infr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_ctrl_init: ERR 1701: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lftr_rcv_t.
+ * This object represents the LinearForwardingTable Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_lft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LFTR_RCV_POOL_MIN_SIZE 32
+#define OSM_LFTR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_lftr_item
+{
+ cl_pool_item_t pool_item;
+ ib_lft_record_t rec;
+
+} osm_lftr_item_t;
+
+typedef struct _osm_lftr_search_ctxt
+{
+ const ib_lft_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ cl_qlist_t* p_list;
+ osm_lftr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_lftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_construct(
+ IN osm_lftr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_destroy(
+ IN osm_lftr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_init(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_lftr_rcv_init );
+
+ osm_lftr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_LFTR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_LFTR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_lftr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_lftr_rcv_new_lftr(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN const osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid,
+ IN ib_net16_t const block )
+{
+ osm_lftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lftr_rcv_new_lftr );
+
+ p_rec_item = (osm_lftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_new_lftr: ERR 4402: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_rcv_new_lftr: "
+ "New LinearForwardingTable: sw 0x%016" PRIx64
+ "\n\t\t\t\tblock 0x%02X lid 0x%02X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ),
+ cl_ntoh16( block ), cl_ntoh16( lid )
+ );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof(ib_lft_record_t) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.block_num = block;
+
+ /* copy the lft block */
+ osm_switch_get_fwd_tbl_block( p_sw, cl_ntoh16(block), p_rec_item->rec.lft );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+osm_port_t*
+__osm_lftr_get_port_by_guid(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN uint64_t port_guid)
+{
+
+ osm_port_t* p_port;
+ CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ port_guid);
+
+ if(p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_get_port_by_guid ERR 4404: "
+ "Invalid port_guid 0x%016" PRIx64 ".\n",
+ port_guid);
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return NULL;
+ }
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+void
+__osm_lftr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_lftr_search_ctxt_t* const p_ctxt =
+ (osm_lftr_search_ctxt_t *)context;
+ const osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ const ib_lft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ osm_lftr_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ ib_net64_t const comp_mask = p_ctxt->comp_mask;
+ const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp;
+ osm_port_t* p_port;
+ uint16_t min_lid_ho, max_lid_ho;
+ uint16_t min_block, max_block, block;
+ uint16_t sw_max_lid_ho, lids_per_block;
+ const osm_physp_t* p_physp;
+
+ /* In switches the port guid is the node guid. */
+ p_port =
+ __osm_lftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid);
+ if (! p_port)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_by_comp_mask: ERR 4405: "
+ "Fail to find Port by Node Guid:0x%016" PRIx64
+ ".\n",
+ cl_ntoh64( p_sw->p_node->node_info.node_guid )
+ );
+ return;
+ }
+
+ /* get the port 0 of the switch */
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+ /* check that the requestor physp and the current physp are under
+ the same partition. */
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_by_comp_mask: ERR 4406: "
+ "Fail to find default physical Port by Node Guid:0x%016" PRIx64
+ ".\n",
+ cl_ntoh64( p_sw->p_node->node_info.node_guid )
+ );
+ return;
+ }
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp ))
+ return;
+
+ /* compare the lids - if required */
+ if( comp_mask & IB_LFTR_COMPMASK_LID )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_rcv_by_comp_mask: "
+ "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\n",
+ cl_ntoh16( p_rcvd_rec->lid ), min_lid_ho, max_lid_ho
+ );
+ /* ok we are ready for range check */
+ if ((min_lid_ho > cl_ntoh16(p_rcvd_rec->lid)) ||
+ (max_lid_ho < cl_ntoh16(p_rcvd_rec->lid)))
+ return;
+ }
+
+ /* now we need to decide which blocks to output */
+ if( comp_mask & IB_LFTR_COMPMASK_BLOCK )
+ {
+ max_block = min_block = cl_ntoh16(p_rcvd_rec->block_num);
+ }
+ else
+ {
+ /* use as many blocks as possible */
+ min_block = 0;
+ sw_max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+ lids_per_block = osm_fwd_tbl_get_lids_per_block( osm_switch_get_fwd_tbl_ptr( p_sw ) );
+ max_block = (max_lid_ho + lids_per_block - 1)/lids_per_block;
+ }
+
+ /* so we can add these blocks one by one ... */
+ for (block = min_block; block <= max_block; block++)
+ __osm_lftr_rcv_new_lftr( p_rcv, p_sw, p_ctxt->p_list,
+ osm_port_get_base_lid(p_port),
+ cl_hton16(block) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_process(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_lft_record_t* p_rcvd_rec;
+ ib_lft_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_lftr_search_ctxt_t context;
+ osm_lftr_item_t* p_rec_item;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_LFT_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4407: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4408: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ cl_qlist_init( &rec_list );
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* Go over all switches */
+ cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+ __osm_lftr_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4409: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_lftr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_lft_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_lftr_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_lftr_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) &&
+ (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_lft_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4410: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_lft_record_t) );
+
+ p_resp_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4411: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lftr_rcv_ctrl_t.
+ * This object represents the LinearForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lftr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lftr_rcv_process( ((osm_lftr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_construct(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_destroy(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_ctrl_init(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lftr_rcv_ctrl_init );
+
+ osm_lftr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LFT_RECORD,
+ __osm_lftr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_ctrl_init: ERR 4501: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lr_rcv_t.
+ * This object represents the LinkRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_link_record.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LR_RCV_POOL_MIN_SIZE 64
+#define OSM_LR_RCV_POOL_GROW_SIZE 64
+
+typedef struct _osm_lr_item
+{
+ cl_pool_item_t pool_item;
+ ib_link_record_t link_rec;
+
+} osm_lr_item_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_construct(
+ IN osm_lr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->lr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_destroy(
+ IN osm_lr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->lr_pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_init(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_lr_rcv_init );
+
+ osm_lr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->lr_pool,
+ OSM_LR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_LR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_lr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__osm_lr_rcv_build_physp_link(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_net16_t from_lid,
+ IN const ib_net16_t to_lid,
+ IN const uint8_t from_port,
+ IN const uint8_t to_port,
+ IN cl_qlist_t* p_list )
+{
+ osm_lr_item_t* p_lr_item;
+
+ p_lr_item = (osm_lr_item_t*)cl_qlock_pool_get( &p_rcv->lr_pool );
+ if( p_lr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_build_physp_link: ERR 1801: "
+ "Unable to acquire link record.\n"
+ "\t\t\t\tFrom port 0x%\n"
+ "\t\t\t\tTo port 0x%\n"
+ "\t\t\t\tFrom lid 0x%\n"
+ "\t\t\t\tTo lid 0x%\n",
+ from_port, to_port,
+ cl_ntoh16(from_lid),
+ cl_ntoh16(to_lid));
+ return;
+ }
+
+ p_lr_item->link_rec.from_port_num = from_port;
+ p_lr_item->link_rec.to_port_num = to_port;
+ p_lr_item->link_rec.to_lid = to_lid;
+ p_lr_item->link_rec.from_lid = from_lid;
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_lr_item->pool_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_lid_range(
+ IN const osm_physp_t* p_physp,
+ OUT uint16_t *p_base_lid,
+ OUT uint16_t *p_max_lid)
+{
+ uint8_t lmc;
+
+ if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+ {
+ *p_base_lid =
+ cl_ntoh16(
+ osm_physp_get_base_lid(
+ osm_node_get_physp_ptr(p_physp->p_node, 0))
+ );
+ *p_max_lid = *p_base_lid;
+ }
+ else
+ {
+ *p_base_lid =
+ cl_ntoh16(osm_physp_get_base_lid(p_physp));
+ lmc = osm_physp_get_lmc( p_physp );
+ *p_max_lid = (uint16_t)(*p_base_lid + (1<<lmc) - 1);
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_physp_link(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_link_record_t* const p_lr,
+ IN const osm_physp_t* p_src_physp,
+ IN const osm_physp_t* p_dest_physp,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list,
+ IN const osm_physp_t* p_req_physp )
+{
+ uint8_t src_port_num;
+ uint8_t dest_port_num;
+ ib_net16_t from_base_lid_ho;
+ ib_net16_t from_max_lid_ho;
+ ib_net16_t to_max_lid_ho;
+ ib_net16_t to_base_lid_ho;
+ uint16_t i, j;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_physp_link );
+
+ /*
+ If only one end of the link is specified, determine
+ the other side.
+ */
+ if( p_src_physp )
+ {
+ if( !osm_physp_is_valid( p_src_physp ) )
+ goto Exit;
+
+ if( p_dest_physp )
+ {
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+ /*
+ Ensure the two physp's are actually connected.
+ If not, bail out.
+ */
+ if( osm_physp_get_remote( p_src_physp ) != p_src_physp )
+ goto Exit;
+ }
+ else
+ {
+ p_dest_physp = osm_physp_get_remote( p_src_physp );
+
+ if(p_dest_physp == NULL)
+ goto Exit;
+
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+
+ }
+
+ }
+ else
+ {
+ if( p_dest_physp )
+ {
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+
+ p_src_physp = osm_physp_get_remote( p_dest_physp );
+
+ if(p_src_physp == NULL)
+ goto Exit;
+ }
+ else
+ goto Exit; /* no physp's, so nothing to do */
+ }
+
+ CL_ASSERT( p_src_physp );
+ CL_ASSERT( p_dest_physp );
+ CL_ASSERT( osm_physp_is_valid( p_src_physp ) );
+ CL_ASSERT( osm_physp_is_valid( p_dest_physp ) );
+
+ /* Check that the p_src_physp, p_dest_physp and p_req_physp
+ all share a pkey (doesn't have to be the same p_key). */
+ if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_dest_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Source and Dest PhysPorts do not share PKey\n");
+ goto Exit;
+ }
+ if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_req_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Source and Requestor PhysPorts do not share PKey\n");
+ goto Exit;
+ }
+ if (! osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_dest_physp) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Requestor and Dest PhysPorts do not share PKey\n");
+ goto Exit;
+ }
+
+ src_port_num = osm_physp_get_port_num( p_src_physp );
+ dest_port_num = osm_physp_get_port_num( p_dest_physp );
+
+ if( comp_mask & IB_LR_COMPMASK_FROM_PORT )
+ if( src_port_num != p_lr->from_port_num )
+ goto Exit;
+
+ if( comp_mask & IB_LR_COMPMASK_TO_PORT )
+ if( dest_port_num != p_lr->to_port_num )
+ goto Exit;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Acquiring link record.\n"
+ "\t\t\t\tsrc port 0x%" PRIx64 " (port 0x%X)"
+ ", dest port 0x%" PRIx64 " (port 0x%X).\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_src_physp ) ),
+ src_port_num,
+ cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ),
+ dest_port_num );
+ }
+
+ if( comp_mask & IB_LR_COMPMASK_FROM_LID )
+ {
+ from_max_lid_ho = from_base_lid_ho =
+ cl_ntoh16(p_lr->from_lid);
+ }else
+ {
+ __get_lid_range(p_src_physp, &from_base_lid_ho,
+ &from_max_lid_ho);
+ }
+
+ if( comp_mask & IB_LR_COMPMASK_TO_LID )
+ {
+ to_max_lid_ho = to_base_lid_ho =
+ cl_ntoh16(p_lr->to_lid);
+ }else
+ {
+ __get_lid_range(p_dest_physp, &to_base_lid_ho,
+ &to_max_lid_ho);
+ }
+
+ for(i=from_base_lid_ho; i<= from_max_lid_ho; i++)
+ {
+ for(j=to_base_lid_ho; j<= to_max_lid_ho; j++)
+ __osm_lr_rcv_build_physp_link(p_rcv, cl_ntoh16(i), cl_ntoh16(j),
+ src_port_num, dest_port_num, p_list);
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_port_links(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_link_record_t* const p_lr,
+ IN const osm_port_t* p_src_port,
+ IN const osm_port_t* p_dest_port,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list,
+ IN const osm_physp_t* p_req_physp )
+{
+ const osm_physp_t* p_src_physp;
+ const osm_physp_t* p_dest_physp;
+ const cl_qmap_t* p_port_tbl;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint8_t dest_num_ports;
+ uint8_t dest_port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_port_links );
+
+ if( p_src_port )
+ {
+ if( p_dest_port )
+ {
+ /*
+ Build an LR for every link connected between both ports.
+ The inner function will discard physp combinations
+ that do not actually connect. Don't bother screening
+ for that here.
+ */
+ num_ports = osm_port_get_num_physp( p_src_port );
+ dest_num_ports = osm_port_get_num_physp( p_dest_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ for( dest_port_num = 1; dest_port_num < dest_num_ports;
+ dest_port_num++ )
+ {
+ p_dest_physp = osm_port_get_phys_ptr( p_dest_port,
+ dest_port_num );
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+ p_dest_physp, comp_mask,
+ p_list, p_req_physp );
+ }
+ }
+ }
+ else
+ {
+ /*
+ Build an LR for every link connected from the source port.
+ */
+ if( comp_mask & IB_LR_COMPMASK_FROM_PORT )
+ {
+ port_num = p_lr->from_port_num;
+ /* If the port number is out of the range of the p_src_port, then
+ this couldn't be a relevant record. */
+ if (port_num < p_src_port->physp_tbl_size)
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+ NULL, comp_mask, p_list,
+ p_req_physp );
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_src_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+ NULL, comp_mask, p_list,
+ p_req_physp );
+ }
+ }
+ }
+ }
+ else
+ {
+ if( p_dest_port )
+ {
+ /*
+ Build an LR for every link connected to the dest port.
+ */
+ if( comp_mask & IB_LR_COMPMASK_TO_PORT )
+ {
+ port_num = p_lr->to_port_num;
+ /* If the port number is out of the range of the p_dest_port, then
+ this couldn't be a relevant record. */
+ if (port_num < p_dest_port->physp_tbl_size )
+ {
+ p_dest_physp = osm_port_get_phys_ptr(
+ p_dest_port, port_num );
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+ p_dest_physp, comp_mask,
+ p_list, p_req_physp );
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_dest_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_dest_physp = osm_port_get_phys_ptr(
+ p_dest_port, port_num );
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+ p_dest_physp, comp_mask,
+ p_list, p_req_physp );
+ }
+ }
+ }
+ else
+ {
+ /*
+ Process the world (recurse once back into this function).
+ */
+ p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+ p_src_port = (osm_port_t*)cl_qmap_head( p_port_tbl );
+
+ while( p_src_port != (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port,
+ NULL, comp_mask, p_list,
+ p_req_physp );
+
+ p_src_port = (osm_port_t*)cl_qmap_next(
+ &p_src_port->map_item );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Returns the SA status to return to the client.
+**********************************************************************/
+static ib_net16_t
+__osm_lr_rcv_get_end_points(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ OUT const osm_port_t** const pp_src_port,
+ OUT const osm_port_t** const pp_dest_port )
+{
+ const ib_link_record_t* p_lr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ ib_api_status_t status;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_end_points );
+
+ /*
+ Determine what fields are valid and then get a pointer
+ to the source and destination port objects, if possible.
+ */
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+ *pp_src_port = NULL;
+ *pp_dest_port = NULL;
+
+ if( p_sa_mad->comp_mask & IB_LR_COMPMASK_FROM_LID )
+ {
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+ cl_ntoh16(p_lr->from_lid),
+ (void**)pp_src_port );
+
+ if( ( (status != CL_SUCCESS) || (*pp_src_port == NULL) ) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ /*
+ This 'error' is the client's fault (bad lid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_get_end_points: "
+ "No source port with LID = 0x%X.\n",
+ cl_ntoh16( p_lr->from_lid ) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+
+ if( p_sa_mad->comp_mask & IB_LR_COMPMASK_TO_LID )
+ {
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+ cl_ntoh16(p_lr->to_lid),
+ (void**)pp_dest_port );
+
+ if( ( (status != CL_SUCCESS) || (*pp_dest_port == NULL) ) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ /*
+ This 'error' is the client's fault (bad lid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_get_end_points: "
+ "No dest port with LID = 0x%X.\n",
+ cl_ntoh16( p_lr->to_lid ) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( sa_status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_respond(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ size_t num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+ size_t trim_num_rec;
+#endif
+ ib_link_record_t* p_resp_lr;
+ ib_api_status_t status;
+ osm_lr_item_t* p_lr_item;
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_respond );
+
+ num_rec = cl_qlist_count( p_list );
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_link_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_respond: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_respond: "
+ "Generating response with %u records.", num_rec );
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_link_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: ERR 1802: "
+ "Unable to allocate MAD.\n" );
+ /* Release the quick pool items */
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /* Copy the header from the request to response */
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_link_record_t) );
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+ cl_memclr( p_resp_lr, sizeof(*p_resp_lr) );
+ }
+ else
+ {
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ /* we need to track the number of copied items so we can
+ * stop the copy - but clear them all
+ */
+ num_copied = 0;
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ /* Copy the Link Records from the list into the MAD */
+ /* only if we did not go over the mad size (since we might trimmed it) */
+ if (num_copied < num_rec)
+ {
+ *p_resp_lr = p_lr_item->link_rec;
+ num_copied++;
+ }
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_resp_lr++;
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ }
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: ERR 1803: "
+ "Unable to send MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_process(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_link_record_t* p_lr;
+ const ib_sa_mad_t* p_sa_mad;
+ const osm_port_t* p_src_port = NULL;
+ const osm_port_t* p_dest_port = NULL;
+ cl_qlist_t lr_list;
+ ib_net16_t sa_status;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ /* we only support SubnAdmGet and SubnAdmGetTable Methods */
+ if ( (p_sa_mad->method != IB_MAD_METHOD_GET) &&
+ (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_process: ERR 1804: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_process: ERR 1805: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_link_record( p_rcv->p_log, p_lr, OSM_LOG_DEBUG );
+
+ cl_qlist_init( &lr_list );
+
+ /*
+ Most SA functions (including this one) are read-only on the
+ subnet object, so we grab the lock non-exclusively.
+ */
+ cl_plock_acquire( p_rcv->p_lock );
+
+ sa_status = __osm_lr_rcv_get_end_points( p_rcv, p_madw,
+ &p_src_port, &p_dest_port );
+
+ if( sa_status != IB_SA_MAD_STATUS_SUCCESS )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port, p_dest_port,
+ p_sa_mad->comp_mask, &lr_list, p_req_physp );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ if( (cl_qlist_count( &lr_list ) == 0) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ __osm_lr_rcv_respond( p_rcv, p_madw, &lr_list );
+
+ Exit:
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lr_rcv_ctrl_t.
+ * This object represents the link record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lr_rcv_process( ((osm_lr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_construct(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_destroy(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lr_rcv_ctrl_init );
+
+ osm_lr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LINK_RECORD,
+ __osm_lr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_ctrl_init: ERR 1901: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_mad_ctrl_t.
+ * This object is part of the SA object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa_response.h>
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_sa_mad_ctrl_disp_done_callback
+ *
+ * DESCRIPTION
+ * This function is the Dispatcher callback that indicates
+ * a received MAD has been processed by the recipient.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_disp_done_callback(
+ IN void* context,
+ IN void* p_data )
+{
+ osm_sa_mad_ctrl_t* const p_ctrl = (osm_sa_mad_ctrl_t*)context;
+ osm_madw_t* const p_madw = (osm_madw_t*)p_data;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_disp_done_callback );
+
+ CL_ASSERT( p_madw );
+ /*
+ Return the MAD & wrapper to the pool.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+/****f* opensm: SA/__osm_sa_mad_ctrl_process_get
+ * NAME
+ * __osm_sa_mad_ctrl_process_get
+ *
+ * DESCRIPTION
+ * This function handles known methods for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_process(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw )
+{
+ ib_sa_mad_t* p_sa_mad;
+ cl_status_t status;
+ cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+ uint64_t last_dispatched_msg_queue_time_msec;
+ uint32_t num_messages;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_process );
+
+ /*
+ If the dispatcher is showing us that it is overloaded
+ there is no point in placing the request in. We should instead provide
+ immediate response - IB_RESOURCE_BUSY
+ But how do we know?
+ The dispatcher reports back the number of outstanding messages and the
+ time the last message stayed in the queue.
+ HACK: Actually, we cannot send a mad within the receive callback,
+ thus - we will just drop it.
+ */
+ cl_disp_get_queue_status(p_ctrl->h_disp,
+ &num_messages,
+ &last_dispatched_msg_queue_time_msec);
+ if ((num_messages > 1) &&
+ (p_ctrl->p_subn->opt.max_msg_fifo_timeout) &&
+ (last_dispatched_msg_queue_time_msec >
+ p_ctrl->p_subn->opt.max_msg_fifo_timeout))
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_INFO,
+ "__osm_sa_mad_ctrl_process: "
+ /* "Responding BUSY status since the dispatcher is already"*/
+ "Dropping mad since the dispatcher is already"
+ " overloaded with %u messages and queue time of:%u[msec]\n",
+ num_messages, last_dispatched_msg_queue_time_msec);
+
+ /* send a busy response */
+ /* osm_sa_send_error( p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */
+
+ /* return the request to the pool */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+
+ goto Exit;
+
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /*
+ Note that attr_id (like the rest of the MAD) is in
+ network byte order.
+ */
+ switch( p_sa_mad->attr_id )
+ {
+ case IB_MAD_ATTR_CLASS_PORT_INFO:
+ msg_id = OSM_MSG_MAD_CLASS_PORT_INFO;
+ break;
+
+ case IB_MAD_ATTR_NODE_RECORD:
+ msg_id = OSM_MSG_MAD_NODE_RECORD;
+ break;
+
+ case IB_MAD_ATTR_PORTINFO_RECORD:
+ msg_id = OSM_MSG_MAD_PORTINFO_RECORD;
+ break;
+
+ case IB_MAD_ATTR_LINK_RECORD:
+ msg_id = OSM_MSG_MAD_LINK_RECORD;
+ break;
+
+ case IB_MAD_ATTR_SMINFO_RECORD:
+ msg_id = OSM_MSG_MAD_SMINFO_RECORD;
+ break;
+
+ case IB_MAD_ATTR_SERVICE_RECORD:
+ msg_id = OSM_MSG_MAD_SERVICE_RECORD;
+ break;
+
+ case IB_MAD_ATTR_PATH_RECORD:
+ msg_id = OSM_MSG_MAD_PATH_RECORD;
+ break;
+
+ case IB_MAD_ATTR_MCMEMBER_RECORD:
+ msg_id = OSM_MSG_MAD_MCMEMBER_RECORD;
+ break;
+
+ case IB_MAD_ATTR_INFORM_INFO:
+ msg_id = OSM_MSG_MAD_INFORM_INFO;
+ break;
+
+ case IB_MAD_ATTR_VLARB_RECORD:
+ msg_id = OSM_MSG_MAD_VL_ARB_RECORD;
+ break;
+
+ case IB_MAD_ATTR_SLVL_RECORD:
+ msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD;
+ break;
+
+ case IB_MAD_ATTR_PKEY_TBL_RECORD:
+ msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD;
+ break;
+
+ case IB_MAD_ATTR_LFT_RECORD:
+ msg_id = OSM_MSG_MAD_LFT_RECORD;
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_process: ERR 1A01: "
+ "Unsupported attribute = 0x%X.\n",
+ cl_ntoh16( p_sa_mad->attr_id ) );
+ osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_ERROR );
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_process: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( msg_id ) );
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sa_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_process: ERR 1A02: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is a known MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sa_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_rcv_callback(
+ IN osm_madw_t *p_madw,
+ IN void *bind_context,
+ IN osm_madw_t *p_req_madw )
+{
+ osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+ ib_sa_mad_t* p_sa_mad;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_rcv_callback );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ A MAD was received from the wire, possibly in response to a request.
+ */
+ cl_atomic_inc( &p_ctrl->p_stats->qp1_mads_rcvd );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "%u QP1 MADs received.\n",
+ p_ctrl->p_stats->qp1_mads_rcvd );
+ }
+
+ /*
+ * C15-0.1.3 requires not responding to any MAD if the SM is
+ * not in active state!
+ * We will not respond if the sm_state is not MASTER, or if the
+ * first_time_master_sweep flag (of the subnet) is TRUE - this
+ * flag indicates that the master still didn't finish its first
+ * sweep, so the subnet is not up and stable yet.
+ */
+ if ( p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "Received SA MAD while SM is not MASTER. MAD ignored.\n");
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+ if ( p_ctrl->p_subn->first_time_master_sweep == TRUE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "Received SA MAD while SM in first sweep. MAD ignored.\n");
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_FRAMES );
+
+ /*
+ * C15-0.1.5 - Table 151: SA Header - p782
+ * SM_key should be either 0 or match the current SM_Key
+ * otherwise discard the MAD.
+ */
+ if ((p_sa_mad->sm_key != 0) &&
+ (p_sa_mad->sm_key != p_ctrl->p_subn->opt.sm_key)) {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_rcv_callback: ERR 1A04: "
+ "Non Zero SA MAD SM_Key: 0x%" PRIx64 " != SM_Key : 0x%" PRIx64
+ " Mad Ignored.\n",
+ cl_ntoh64(p_sa_mad->sm_key),
+ cl_ntoh64(p_ctrl->p_subn->opt.sm_key)
+ );
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+
+ switch( p_sa_mad->method )
+ {
+ case IB_MAD_METHOD_REPORT_RESP:
+ /* we do not really do anything with report represses -
+ just retire the transaction */
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "Received Report Repress. Retiring the transaction.\n");
+
+ if (p_req_madw)
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_req_madw );
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+
+ break;
+
+ case IB_MAD_METHOD_GET:
+ case IB_MAD_METHOD_GETTABLE:
+ case IB_MAD_METHOD_SET:
+ case IB_MAD_METHOD_DELETE:
+ __osm_sa_mad_ctrl_process( p_ctrl, p_madw );
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_rcv_callback: ERR 1A05: "
+ "Not yet implemented Method=<0x%X> Attribute=<0x%X>",
+ p_sa_mad->method,p_sa_mad->attr_id);
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_send_err_callback
+ * NAME
+ * __osm_sa_mad_ctrl_send_err_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for send errors
+ * on MADs that were expecting a response.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sa_mad_ctrl_send_err_callback(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_send_err_callback );
+
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_send_err_callback: ERR 1A06: "
+ "MAD transaction completed in error.\n" );
+
+ /*
+ We should never be here since the SA never originates a request.
+ Unless we generated a Report(Notice)
+ */
+ CL_ASSERT( p_madw );
+ CL_ASSERT( p_madw->resp_expected == TRUE);
+
+ /*
+ An error occurred. No response was received to a request MAD.
+ Retire the original request MAD.
+ */
+
+ osm_dump_sa_mad(p_ctrl->p_log, osm_madw_get_sa_mad_ptr( p_madw ),
+ OSM_LOG_ERROR );
+
+ /* __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); */
+
+ if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+ {
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_send_err_callback: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ osm_madw_get_err_msg( p_madw ),
+ p_madw,
+ __osm_sa_mad_ctrl_disp_done_callback,
+ p_ctrl );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_send_err_callback: ERR 1A07: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+ else
+ {
+ /*
+ No error message was provided, just retire the MAD.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_mad_ctrl_construct(
+ IN osm_sa_mad_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_mad_ctrl_destroy(
+ IN osm_sa_mad_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_init(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_mad_ctrl_init );
+
+ osm_sa_mad_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_mad_pool = p_mad_pool;
+ p_ctrl->p_vendor = p_vendor;
+ p_ctrl->p_stats = p_stats;
+ p_ctrl->p_subn = p_subn;
+ p_ctrl->p_resp = p_resp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ CL_DISP_MSGID_NONE,
+ NULL,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_init: ERR 1A08: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_bind(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN const ib_net64_t port_guid )
+{
+ osm_bind_info_t bind_info;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_bind );
+
+ if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_bind: ERR 1A09: "
+ "Multiple binds not allowed. Call unbind first. " );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ bind_info.class_version = 2;
+ bind_info.is_responder = TRUE;
+ bind_info.is_report_processor = FALSE;
+ bind_info.is_trap_processor = FALSE;
+ bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+ bind_info.port_guid = port_guid;
+ bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
+ bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
+
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "osm_sa_mad_ctrl_bind: "
+ "Binding to port GUID 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+
+ p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor,
+ &bind_info,
+ p_ctrl->p_mad_pool,
+ __osm_sa_mad_ctrl_rcv_callback,
+ __osm_sa_mad_ctrl_send_err_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ status = IB_ERROR;
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_bind: ERR 1A10: "
+ "Vendor specific bind() failed (%s).\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_unbind(
+ IN osm_sa_mad_ctrl_t* const p_ctrl)
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_unbind );
+
+ if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_unbind: ERR 1A11: "
+ "No previous bind. Call bind first.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_vendor_unbind( p_ctrl->h_bind );
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+ return( status );
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcmr_recv_t.
+ * This object represents the MCMemberRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_inform.h>
+
+#define OSM_MCMR_RCV_POOL_MIN_SIZE 32
+#define OSM_MCMR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_mcmr_item
+{
+ cl_pool_item_t pool_item;
+ ib_member_rec_t rec;
+
+} osm_mcmr_item_t;
+
+typedef struct osm_sa_mcmr_search_ctxt {
+ const ib_member_rec_t *p_mcmember_rec;
+ osm_mgrp_t *p_mgrp;
+ osm_mcmr_recv_t *p_rcv;
+ cl_qlist_t *p_list; /* hold results */
+ ib_net64_t comp_mask;
+ const osm_physp_t* p_req_physp;
+} osm_sa_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_construct(
+ IN osm_mcmr_recv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_destroy(
+ IN osm_mcmr_recv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_mcmr_rcv_init );
+
+ osm_mcmr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_sm = p_sm;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+ p_rcv->mlid_ho = 0xC000;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_MCMR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_MCMR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_mcmr_item_t),
+ NULL, NULL, NULL );
+ if (status != CL_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_init: ERR 1B02: "
+ "Error Init of qlock pool (%d).\n",
+ status );
+ }
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ A search function that compares the given mgrp with the search context
+ if there is a match by mgid the p_mgrp is copied to the search context
+ p_mgrp component
+
+ Inputs:
+ p_map_item - which is part of a mgrp object
+ context - points to the osm_sa_mcmr_search_ctxt_t including the mgid
+ looked for and the result p_mgrp
+**********************************************************************/
+static
+void
+__search_mgrp_by_mgid(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item;
+ osm_sa_mcmr_search_ctxt_t *p_ctxt = (osm_sa_mcmr_search_ctxt_t *) context;
+ const ib_member_rec_t *p_recvd_mcmember_rec;
+ osm_mcmr_recv_t *p_rcv;
+
+ p_recvd_mcmember_rec = p_ctxt->p_mcmember_rec;
+ p_rcv = p_ctxt->p_rcv;
+
+ /* ignore groups marked for deletion */
+ if (p_mgrp->to_be_deleted)
+ return;
+
+ /* compare entire MGID so different scope will not sneak in for
+ the same MGID */
+ if (cl_memcmp(&p_mgrp->mcmember_rec.mgid,
+ &p_recvd_mcmember_rec->mgid,
+ sizeof(ib_gid_t)))
+ return;
+
+ if(p_ctxt->p_mgrp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__search_mgrp_by_mgid: ERR 1B03: "
+ "Multiple MCGROUP for same MGID.\n" );
+ return;
+ }
+ p_ctxt->p_mgrp = p_mgrp;
+
+}
+
+/**********************************************************************
+ Look for a MGRP in the mgrp_mlid_tbl by mlid
+**********************************************************************/
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net16_t const mlid)
+{
+ cl_map_item_t *map_item;
+
+ map_item = cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl,
+ mlid);
+ if(map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+ {
+ return NULL;
+ }
+ return (osm_mgrp_t *)map_item;
+
+}
+
+/**********************************************************************
+Look for a MGRP in the mgrp_mlid_tbl by mgid
+***********************************************************************/
+static ib_api_status_t
+__get_mgrp_by_mgid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_member_rec_t* p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ osm_sa_mcmr_search_ctxt_t mcmr_search_context;
+
+ mcmr_search_context.p_mcmember_rec = p_recvd_mcmember_rec;
+ mcmr_search_context.p_rcv = p_rcv;
+ mcmr_search_context.p_mgrp = NULL;
+
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+ __search_mgrp_by_mgid,
+ &mcmr_search_context);
+
+ if(mcmr_search_context.p_mgrp == NULL)
+ {
+ return IB_NOT_FOUND;
+ }
+
+ *pp_mgrp = mcmr_search_context.p_mgrp;
+ return IB_SUCCESS;
+}
+
+/*********************************************************************
+copy certain fields between two mcmember records
+used during the process of join request to copy data from the mgrp to the
+port record.
+**********************************************************************/
+static inline void
+__copy_from_create_mc_rec(
+ IN ib_member_rec_t * const dest,
+ IN const ib_member_rec_t *const src)
+{
+ dest->qkey = src->qkey;
+ dest->mlid = src->mlid;
+ dest->tclass = src->tclass;
+ dest->pkey = src->pkey;
+ dest->sl_flow_hop = src->sl_flow_hop;
+ dest->mtu = src->mtu;
+ dest->rate = src->rate;
+ dest->pkt_life = src->pkt_life;
+}
+
+/*********************************************************************
+Return an mlid to the pool of free mlids.
+But this implementation is not a pool - it is simply scanning through
+the MGRP database for unused mlids...
+*********************************************************************/
+static void
+__free_mlid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN uint16_t mlid)
+{
+ UNUSED_PARAM(p_rcv);
+ UNUSED_PARAM(mlid);
+}
+
+/*********************************************************************
+Get a new unused mlid by scanning all the used ones in the subnet.
+TODO: Implement a more scalable - O(1) solution based on pool of
+available mlids.
+**********************************************************************/
+static ib_net16_t
+__get_new_mlid(
+ IN osm_mcmr_recv_t* const p_rcv)
+{
+ osm_subn_t *p_subn = p_rcv->p_subn;
+ osm_mgrp_t *p_mgrp;
+ uint8_t *used_mlids_array;
+ uint16_t idx;
+ uint16_t mlid; /* the result */
+ uint16_t max_num_mlids;
+
+ OSM_LOG_ENTER(p_rcv->p_log, __get_new_mlid);
+
+ /* If empty MCGroups table - at first return the min mlid */
+ p_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+ if (p_mgrp == (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ))
+ {
+ mlid = IB_LID_MCAST_START_HO;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_new_mlid: "
+ "No multicast groups found using minimal mlid:0x%04X\n",
+ mlid );
+ goto Exit;
+ }
+
+ max_num_mlids =
+ p_rcv->p_subn->max_multicast_lid_ho - IB_LID_MCAST_START_HO;
+
+ /* track all used mlids in the array (by mlid index) */
+ used_mlids_array =
+ (uint8_t *)cl_zalloc(sizeof(uint8_t)*max_num_mlids);
+
+ /* scan all available multicast groups in the DB and fill in the table */
+ while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+ {
+ /* ignore mgrps marked for deletion */
+ if (p_mgrp->to_be_deleted == FALSE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__get_new_mlid: "
+ "Found mgrp with lid:0x%X MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh16( p_mgrp->mlid),
+ cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.prefix ),
+ cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.interface_id ) );
+
+ /* Map in table */
+ if (cl_ntoh16(p_mgrp->mlid) > p_rcv->p_subn->max_multicast_lid_ho)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_new_mlid: ERR 1B27: "
+ "Found mgrp with mlid:0x%04X > max allowed mlid:0x%04X\n",
+ cl_ntoh16(p_mgrp->mlid),
+ max_num_mlids + IB_LID_MCAST_START_HO);
+ }
+ else
+ {
+ used_mlids_array[cl_ntoh16(p_mgrp->mlid) - IB_LID_MCAST_START_HO] = 1;
+ }
+ }
+ p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ /* Find "mlid holes" in the mgrp table */
+ for (idx = 0;
+ (idx < max_num_mlids) && (used_mlids_array[idx] == 1);
+ idx++);
+
+ /* did it go above the maximal mlid allowed */
+ if ( idx < max_num_mlids )
+ {
+ mlid = idx + IB_LID_MCAST_START_HO;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_new_mlid: "
+ "Found available mlid:0x%04X at idx:%u\n",
+ mlid, idx);
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_new_mlid: ERR 1B23: "
+ "All available:%u mlids are taken\n",
+ max_num_mlids);
+ mlid = 0;
+ }
+
+ cl_free(used_mlids_array);
+
+ Exit:
+ OSM_LOG_EXIT(p_rcv->p_log);
+ return cl_hton16(mlid);
+}
+
+/*********************************************************************
+This procedure is only invoked to cleanup INTERMEDIATE mgrp.
+If there is only one port on the mgrp it means that the current
+request was the only member and the group is not really needed. So we
+silently drop it. Since it was an intermediate group no need to
+re-route it.
+**********************************************************************/
+static void
+__cleanup_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net16_t const mlid)
+{
+ osm_mgrp_t *p_mgrp;
+
+ p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+ if(p_mgrp)
+ {
+ /* Remove MGRP only if osm_mcm_port_t count is 0 and
+ * Not a well known group
+ */
+ if(cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) &&
+ (p_mgrp->well_known == FALSE))
+ {
+ cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_mgrp );
+ osm_mgrp_destroy(p_mgrp);
+ }
+ }
+}
+
+/*********************************************************************
+Add a port to the group. Calculating its PROXY_JOIN by the Port and
+requestor gids.
+**********************************************************************/
+static
+ib_api_status_t
+__add_new_mgrp_port(
+ IN osm_mcmr_recv_t * p_rcv,
+ IN osm_mgrp_t *p_mgrp,
+ IN ib_member_rec_t *p_recvd_mcmember_rec,
+ IN osm_mad_addr_t *p_mad_addr,
+ OUT osm_mcm_port_t **pp_mcmr_port)
+{
+ boolean_t proxy_join;
+ ib_gid_t requestor_gid;
+
+ /* set the proxy_join if the requestor gid is not identical to the
+ joined gid */
+ requestor_gid = osm_get_gid_by_mad_addr( p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr );
+
+ if (! cl_memcmp(&p_recvd_mcmember_rec->port_gid, &requestor_gid,
+ sizeof(ib_gid_t)))
+ {
+ proxy_join = FALSE;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__add_new_mgrp_port: "
+ "create new port with proxy_join FALSE\n");
+ }
+ else
+ {
+ /* The port is not the one specified in PortGID.
+ The check that the requestor is in the same partition as
+ the PortGID is done before - just need to update the proxy_join. */
+ proxy_join = TRUE;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__add_new_mgrp_port: "
+ "create new port with proxy_join TRUE\n");
+ }
+
+ *pp_mcmr_port = osm_mgrp_add_port(p_mgrp,
+ &p_recvd_mcmember_rec->port_gid,
+ p_recvd_mcmember_rec->scope_state,
+ proxy_join );
+ if(*pp_mcmr_port == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__add_new_mgrp_port: ERR 1B06: "
+ "osm_mgrp_add_port failed\n");
+
+ return IB_INSUFFICIENT_MEMORY;
+ }
+
+ return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__check_join_comp_mask(ib_net64_t comp_mask)
+{
+ return( (comp_mask & JOIN_MC_COMP_MASK) == JOIN_MC_COMP_MASK);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__check_create_comp_mask(ib_net64_t comp_mask,
+ ib_member_rec_t *p_recvd_mcmember_rec)
+{
+ return(
+ ((comp_mask & REQUIRED_MC_CREATE_COMP_MASK) == REQUIRED_MC_CREATE_COMP_MASK)
+ );
+}
+
+/**********************************************************************
+Generate the response MAD
+**********************************************************************/
+static void
+__osm_mcmr_rcv_respond(
+ IN const osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN ib_member_rec_t *p_mcmember_rec )
+{
+ osm_madw_t *p_resp_madw;
+ ib_sa_mad_t *p_sa_mad, *p_resp_sa_mad;
+ ib_member_rec_t *p_resp_mcmember_rec;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_respond );
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get(p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ sizeof(ib_member_rec_t)+IB_SA_MAD_HDR_SIZE,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if ( !p_resp_madw)
+ {
+ goto Exit;
+ }
+
+ p_resp_sa_mad = (ib_sa_mad_t*)p_resp_madw->p_mad;
+ p_sa_mad = (ib_sa_mad_t*)p_madw->p_mad;
+ /* Copy the MAD header back into the response mad */
+ cl_memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE);
+ /* based on the current method decide about the response: */
+ if ((p_resp_sa_mad->method == IB_MAD_METHOD_GET) ||
+ (p_resp_sa_mad->method == IB_MAD_METHOD_SET)) {
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+ } else if (p_resp_sa_mad->method == IB_MAD_METHOD_DELETE) {
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ }
+ else
+ {
+ CL_ASSERT( p_resp_sa_mad->method == 0);
+ }
+
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_member_rec_t) );
+ p_resp_mcmember_rec = (ib_member_rec_t*)&p_resp_sa_mad->data;
+
+ *p_resp_mcmember_rec = *p_mcmember_rec;
+
+ /* Fill in the mtu, rate, and packet lifetime selectors */
+ p_resp_mcmember_rec->mtu |= 2<<6; /* exactly */
+ p_resp_mcmember_rec->rate |= 2<<6; /* exactly */
+ p_resp_mcmember_rec->pkt_life |= 2<<6; /* exactly */
+
+ status = osm_vendor_send(
+ p_resp_madw->h_bind,
+ p_resp_madw,
+ FALSE);
+
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_respond: ERR 1B07: \n"
+ "for TID = <0x%"PRIx64">\n", p_resp_sa_mad->trans_id);
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/*********************************************************************
+In joining an existing group, or when querying the mc groups,
+we make sure the following components provided match: MTU and RATE
+HACK: Currently we ignore the PKT_LIFETIME field.
+**********************************************************************/
+static boolean_t
+__validate_more_comp_fields(
+ osm_log_t *p_log,
+ const osm_mgrp_t *p_mgrp,
+ const ib_member_rec_t *p_recvd_mcmember_rec,
+ ib_net64_t comp_mask)
+{
+ uint8_t mtu_sel;
+ uint8_t mtu_required;
+ uint8_t mtu_mgrp;
+ uint8_t rate_sel;
+ uint8_t rate_required;
+ uint8_t rate_mgrp;
+
+ if ( comp_mask & IB_MCR_COMPMASK_MTU_SEL)
+ {
+ mtu_sel = (uint8_t)(p_recvd_mcmember_rec->mtu >> 6);
+ /* Clearing last 2 bits */
+ mtu_required = (uint8_t)(p_recvd_mcmember_rec->mtu & 0x3F);
+ mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F);
+ switch (mtu_sel)
+ {
+ case 0: /* Greater than MTU specified */
+ if(mtu_mgrp <= mtu_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x is not greater than %x\n",
+ mtu_mgrp, mtu_required);
+ return FALSE;
+ }
+ break;
+ case 1: /* Less than MTU specified */
+ if(mtu_mgrp >= mtu_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x is not less than %x\n",
+ mtu_mgrp, mtu_required);
+ return FALSE;
+ }
+ break;
+ case 2: /* Exactly MTU specified */
+ if(mtu_mgrp != mtu_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x is not equal to %x\n",
+ mtu_mgrp, mtu_required);
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* what about rate ? */
+ if ( comp_mask & IB_MCR_COMPMASK_RATE_SEL)
+ {
+ rate_sel = (uint8_t)(p_recvd_mcmember_rec->rate >> 6);
+ /* Clearing last 2 bits */
+ rate_required = (uint8_t)(p_recvd_mcmember_rec->rate & 0x3F);
+ rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F);
+ switch (rate_sel)
+ {
+ case 0: /* Greater than RATE specified */
+ if(rate_mgrp <= rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x is not greater than %x\n",
+ rate_mgrp, rate_required);
+ return FALSE;
+ }
+ break;
+ case 1: /* Less than RATE specified */
+ if(rate_mgrp >= rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x is not less than %x\n",
+ rate_mgrp, rate_required);
+ return FALSE;
+ }
+ break;
+ case 2: /* Exactly RATE specified */
+ if(rate_mgrp != rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x is not equal to %x\n",
+ rate_mgrp, rate_required);
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/**********************************************************************
+ * o15-0.2.1: If SA supports UD multicast, then if SA receives a SubnAdmSet()
+ * or SubnAdmDelete() method that would modify an existing
+ * MCMemberRecord, SA shall not modify that MCMemberRecord and shall
+ * return an error status of ERR_REQ_INVALID in response in the
+ * following cases:
+ * 1. Saved MCMemberRecord.ProxyJoin is not set and the request is
+ * issued by a requester with a GID other than the Port-GID.
+ * 2. Saved MCMemberRecord.ProxyJoin is set and the requester is not
+ * part of the partition for that MCMemberRecord.
+ **********************************************************************/
+static boolean_t
+__validate_modify(IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_mgrp_t* p_mgrp,
+ IN osm_mad_addr_t* p_mad_addr,
+ IN ib_member_rec_t* p_recvd_mcmember_rec,
+ OUT osm_mcm_port_t **pp_mcm_port) {
+ ib_net64_t portguid;
+ ib_gid_t request_gid;
+ osm_physp_t* p_request_physp;
+
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ *pp_mcm_port = NULL;
+
+ /* o15-0.2.1 : If this is a new port adding - nothing to check */
+ if (! osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "This is a new port in the mgroup\n");
+ return TRUE;
+ }
+
+ /* We validate the request according the the proxy_join.
+ Check if the proxy_join is set or not */
+ if ( (*pp_mcm_port)->proxy_join == FALSE )
+ {
+ /* The proxy_join is not set. Modifying can by done only
+ if the requestor GID == PortGID */
+ request_gid = osm_get_gid_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr );
+
+ if (cl_memcmp(&((*pp_mcm_port)->port_gid), &request_gid, sizeof(ib_gid_t)))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "No ProxyJoin but different ports: stored:0x%016"PRIx64
+ " request:0x%016"PRIx64"\n",
+ cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+ cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+ );
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* the proxy_join is set. Modification allowed only if the
+ requestor is part of the partition for this MCMemberRecord */
+ p_request_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr );
+ if (p_request_physp == NULL)
+ return FALSE;
+
+
+ if ( ! osm_physp_has_pkey(p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+ p_request_physp ))
+ {
+ /* the request port is not part of the partition for this mgrp */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "ProxyJoin but port not in partition. stored:0x%016"PRIx64
+ " request:0x%016"PRIx64"\n",
+ cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+ cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+ );
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Check legality of the requested MGID DELETE
+ * o15-0.1.14 = VALID DELETE:
+ * To be a valid delete MAD needs to:
+ * 1 the MADs PortGID and MGID components match the PortGID and
+ * MGID of a stored MCMemberRecord;
+ * 2 the MADs JoinState component contains at least one bit set to 1
+ * in the same position as that stored MCMemberRecords JoinState
+ * has a bit set to 1,
+ * i.e., the logical AND of the two JoinState components
+ * is not all zeros;
+ * 3 the MADs JoinState component does not have some bits set
+ * which are not set in the stored MCMemberRecords JoinState component;
+ * 4 either the stored MCMemberRecord:ProxyJoin is reset (0), and the
+ * MADs source is the stored PortGID;
+ * OR
+ * the stored MCMemberRecord:ProxyJoin is set (1), (see o15-
+ * 0.1.2:); and the MADs source is a member of the partition indicated
+ * by the stored MCMemberRecord:P_Key.
+ */
+static boolean_t
+__validate_delete(IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_mgrp_t *p_mgrp,
+ IN osm_mad_addr_t* p_mad_addr,
+ IN ib_member_rec_t* p_recvd_mcmember_rec,
+ OUT osm_mcm_port_t **pp_mcm_port) {
+ ib_net64_t portguid;
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ *pp_mcm_port = NULL;
+
+ /* 1 */
+ if (! osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "Failed to find the port in the mgroup\n");
+ return FALSE;
+ }
+
+ /* 2 */
+ if (! (p_recvd_mcmember_rec->scope_state & 0x0F &
+ (*pp_mcm_port)->scope_state))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "Could not find any matching bits in the stored and requested JoinState\n");
+ return FALSE;
+ }
+
+ /* 3 */
+ if ( ((p_recvd_mcmember_rec->scope_state & 0x0F) |
+ (0x0F & (*pp_mcm_port)->scope_state)) !=
+ (0x0F & (*pp_mcm_port)->scope_state))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "Some bits in the request JoinState (0x%X) are not set in the stored port (0x%X).\n",
+ (p_recvd_mcmember_rec->scope_state & 0x0F),
+ (0x0F & (*pp_mcm_port)->scope_state)
+ );
+ return FALSE;
+ }
+
+ /* 4 */
+ /* Validate according the the proxy_join (o15-0.1.2) */
+ if ( __validate_modify( p_rcv, p_mgrp, p_mad_addr, p_recvd_mcmember_rec,
+ pp_mcm_port ) == FALSE )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "proxy_join validation failure.\n" );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Check legality of the requested MGID (note this does not hold for SA
+ * created MGIDs
+ *
+ * Implementing o16.0.1.6:
+ * A multicast GID is considered to be invalid if:
+ * 1. It does not comply with the rules as specified in 4.1.1 "GID Usage and
+ * Properties" on page 133:
+ *
+ * 14) The multicast GID format is (bytes are comma sep):
+ * 0xff,<Fl><Sc>,<Si>,<Si>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<Id>,<Id>,<Id>,<Id>
+ * Fl 4bit = Flags (b)
+ * Sc 4bit = Scope (c)
+ * Si 16bit = Signature (2)
+ * P 64bit = GID Prefix (should be a subnet unique ID - normally Subnet Prefix)
+ * Id 32bit = Unique ID in the Subnet (might be MLID or Pkey ?)
+ *
+ * a) 8-bits of 11111111 at the start of the GID identifies this as being a
+ * multicast GID.
+ * b) Flags is a set of four 1-bit flags: 000T with three flags reserved
+ * and defined as zero (0). The T flag is defined as follows:
+ * i) T = 0 indicates this is a permanently assigned (i.e. wellknown)
+ * multicast GID. See RFC 2373 and RFC 2375 as reference
+ * for these permanently assigned GIDs.
+ * ii) T = 1 indicates this is a non-permanently assigned (i.e. transient)
+ * multicast GID.
+ * c) Scope is a 4-bit multicast scope value used to limit the scope of
+ * the multicast group. The following table defines scope value and
+ * interpretation.
+ *
+ * Multicast Address Scope Values:
+ * 0x2 Link-local
+ * 0x5 Site-local
+ * 0x8 Organization-local
+ * 0xE Global
+ *
+ * 2. It contains the SA-specific signature of 0xA01B and has the link-local
+ * scope bits set. (EZ: the idea here is that SA created MGIDs are the
+ * only source for this signature with link-local scope)
+ */
+ib_api_status_t
+__validate_requested_mgid(IN osm_mcmr_recv_t* const p_rcv,
+ IN const ib_member_rec_t* p_mcm_rec) {
+
+ uint16_t signature;
+ boolean_t valid = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_requested_mgid );
+
+ /* 14-a : mcast GID must start with 0xFF */
+ if (p_mcm_rec->mgid.multicast.header[0] != 0xFF)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B01: "
+ "Wrong MGID Prefix 0x%02X Must be 0xFF.\n",
+ cl_ntoh16(p_mcm_rec->mgid.multicast.header[0])
+ );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /* the MGID signature can mark IPoIB or SA assigned MGIDs */
+ cl_memcpy(&signature, &(p_mcm_rec->mgid.multicast.raw_group_id), sizeof(signature));
+ signature = cl_ntoh16(signature);
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_requested_mgid: "
+ "MGID Signed as 0x%04X.\n",
+ signature
+ );
+
+ /*
+ * We skip any checks for MGIDs that follow IPoIB
+ * GID structure as defined by the IETF ipoib-link-multicast.
+ *
+ * For IPv4 over IB, the signature will be "0x401B".
+ *
+ * | 8 | 4 | 4 | 16 bits | 16 bits | 48 bits | 32 bits |
+ * +--------+----+----+-----------------+---------+----------+---------+
+ * |11111111|0001|scop|<IPoIB signature>|< P_Key >|00.......0|<all 1's>|
+ * +--------+----+----+-----------------+---------+----------+---------+
+ *
+ * For IPv6 over IB, the signature will be "0x601B".
+ *
+ * | 8 | 4 | 4 | 16 bits | 16 bits | 80 bits |
+ * +--------+----+----+-----------------+---------+--------------------+
+ * |11111111|0001|scop|<IPoIB signature>|< P_Key >|000.............0001|
+ * +--------+----+----+-----------------+---------+--------------------+
+ *
+ */
+ if (signature == 0x401B || signature == 0x601B)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_requested_mgid: "
+ "Skipping MGID Validation for IPoIB Signed (0x%04X) MGIDs.\n",
+ signature
+ );
+ goto Exit;
+ }
+
+ /* 14-b: the 3 upper bits in the "flags" should be zero: */
+ if ( p_mcm_rec->mgid.multicast.header[1] & 0xE0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B28: "
+ "MGID Uses Reserved Flags: flags=0x%X.\n",
+ (p_mcm_rec->mgid.multicast.header[1] & 0xE0) >> 4
+ );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /* 2 - now what if the link local format 0xA01B is used -
+ the scope should not be link local */
+ if ( ( signature == 0xA01B ) &&
+ ((p_mcm_rec->mgid.multicast.header[1] & 0x0F) == 0x02) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B24: "
+ "MGID Uses 0xA01B signature but with link-local scope.\n");
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /*
+ * There is no real way to make sure the Unique MGID Prefix is really unique.
+ * If we could enforce using the Subnet Prefix for that purpose it would
+ * have been nice. But the spec does not require it.
+ */
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return (valid);
+}
+
+/**********************************************************************
+ Check if the requested new mgroup parameters are realizable.
+ Also set the default MTU and Rate if not provided by the user.
+**********************************************************************/
+boolean_t
+__mgrp_request_is_realizable(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN ib_member_rec_t * p_mcm_rec)
+{
+ uint8_t mtu_sel;
+ uint8_t mtu_required;
+ uint8_t rate_sel;
+ uint8_t rate_required;
+ osm_log_t *p_log = p_rcv->p_log;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __mgrp_request_is_realizable);
+
+ /*
+ * End of o15-0.1.6 specifies:
+ * ....
+ * The entity may also supply the other components such as HopLimit, MTU,
+ * etc. during group creation time. If these components are not provided
+ * during group creation time, SA will provide them for the group. The values
+ * chosen are vendor-dependent and beyond the scope of the specification.
+ *
+ * so we might also need to assign RATE/MTU if they are not comp masked in.
+ */
+ if (! (comp_mask & IB_MCR_COMPMASK_MTU))
+ {
+ p_mcm_rec->mtu = p_rcv->p_subn->min_ca_mtu;
+ }
+ else
+ {
+ /* we need to select an MTU based on the requested MTU and selector */
+ if ( comp_mask & IB_MCR_COMPMASK_MTU_SEL)
+ {
+ mtu_sel = (uint8_t)(p_mcm_rec->mtu >> 6);
+ }
+ else
+ {
+ /* by default we assume an exact mtu is requested */
+ mtu_sel = 2;
+ }
+
+ /* Clearing last 2 bits */
+ mtu_required = (uint8_t)(p_mcm_rec->mtu & 0x3F);
+
+ switch (mtu_sel)
+ {
+ case 0: /* Greater than MTU specified */
+ /* we provide the largest MTU possible if we can */
+ if (mtu_required < p_rcv->p_subn->min_ca_mtu)
+ {
+ p_mcm_rec->mtu = p_rcv->p_subn->min_ca_mtu;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Requested MTU %x >= the maximal possible:%x \n",
+ mtu_required, p_rcv->p_subn->min_ca_mtu);
+ return FALSE;
+ }
+ break;
+ case 1: /* Less than MTU specified */
+ /* if the requested MTU is not already the minimal we just
+ use one lower */
+ if ( mtu_required > 1 )
+ {
+ p_mcm_rec->mtu--;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Can not obtain a lower MTU then the given one:%x\n",
+ mtu_required);
+ return FALSE;
+ }
+ break;
+ case 2: /* Exactly MTU specified */
+ /* make sure it is in the range */
+ if ((1 > mtu_required) || (mtu_required > p_rcv->p_subn->min_ca_mtu))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Requested MTU %x out of range: 1 .. %x \n",
+ mtu_required, p_rcv->p_subn->min_ca_mtu);
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (! (comp_mask & IB_MCR_COMPMASK_RATE))
+ {
+ p_mcm_rec->rate = p_rcv->p_subn->min_ca_rate;
+ }
+ else
+ {
+ /* we need to select an RATE based on the requested RATE and selector */
+ if ( comp_mask & IB_MCR_COMPMASK_RATE_SEL)
+ {
+ rate_sel = (uint8_t)(p_mcm_rec->rate >> 6);
+ }
+ else
+ {
+ /* by default we assume an exact rate is requested */
+ rate_sel = 2;
+ }
+
+ /* Clearing last 2 bits */
+ rate_required = (uint8_t)(p_mcm_rec->rate & 0x3F);
+
+ switch (rate_sel)
+ {
+ case 0: /* Greater than RATE specified */
+ /* we provide the largest RATE possible if we can */
+ if (rate_required < p_rcv->p_subn->min_ca_rate)
+ {
+ p_mcm_rec->rate = p_rcv->p_subn->min_ca_rate;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Requested RATE %x >= the maximal possible:%x \n",
+ rate_required, p_rcv->p_subn->min_ca_rate);
+ return FALSE;
+ }
+ break;
+ case 1: /* Less than RATE specified */
+ /* if the requested RATE is not already the minimal we just
+ use one lower */
+ if ( rate_required > 2 )
+ {
+ p_mcm_rec->rate--;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Can not obtain a lower RATE then the given one:%x\n",
+ rate_required);
+ return FALSE;
+ }
+ break;
+ case 2: /* Exactly RATE specified */
+ /* make sure it is in the range */
+ if ((2 > rate_required) || (rate_required > p_rcv->p_subn->min_ca_rate))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Requested RATE %x out of range: 2 .. %x \n",
+ rate_required, p_rcv->p_subn->min_ca_rate);
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return TRUE;
+}
+
+/**********************************************************************
+ Call this function to create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN const ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ ib_net16_t mlid;
+ uint8_t zero_mgid, valid;
+ uint8_t scope, i;
+ ib_gid_t *p_mgid;
+ osm_mgrp_t *p_prev_mgrp;
+ ib_api_status_t status = IB_SUCCESS;
+
+ /* copy for modifications */
+ ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_create_new_mgrp );
+
+ /* but what if the given MGID was not 0 ? */
+ zero_mgid = 1;
+ for ( i = 0 ; i < sizeof(p_recvd_mcmember_rec->mgid); i++) {
+ if (p_recvd_mcmember_rec->mgid.raw[i] != 0)
+ {
+ zero_mgid = 0;
+ break;
+ }
+ }
+
+ /*
+ we allocate a new mlid number before we might use it
+ for MGID ...
+ */
+ mlid = __get_new_mlid(p_rcv);
+ if ( mlid == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B19: "
+ "__get_new_mlid failed.\n");
+ status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ goto Exit;
+ }
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Getting new mlid 0x%x.\n", cl_ntoh16(mlid));
+
+ /* we need to create the new MGID if it was not defined */
+ if (zero_mgid)
+ {
+ /* create a new MGID */
+
+ /* use the given scope state only if requested! */
+ if (comp_mask & IB_MCR_COMPMASK_SCOPE)
+ {
+ ib_member_get_scope_state(
+ p_recvd_mcmember_rec->scope_state, &scope, NULL);
+ }
+ else
+ {
+ /* to guarantee no collision with other subnets use local scope! */
+ scope = 0x02; /* link-local scope */
+ }
+
+ p_mgid = &(mcm_rec.mgid);
+ p_mgid->raw[0] = 0xFF;
+ p_mgid->raw[1] = 0x10 | scope;
+ p_mgid->raw[2] = 0xA0;
+ p_mgid->raw[3] = 0x1B;
+
+ /* HACK: I will be using the SA port gid for making it globally unique */
+ cl_memcpy((&p_mgid->raw[4]),
+ &p_rcv->p_subn->opt.subnet_prefix, sizeof(uint64_t));
+
+ /* HACK how do we get a unique number - use the mlid twice */
+ cl_memcpy(&p_mgid->raw[10], &mlid, sizeof(uint16_t));
+ cl_memcpy(&p_mgid->raw[12], &mlid, sizeof(uint16_t));
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Allocated new MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64(p_mgid->unicast.prefix),
+ cl_ntoh64(p_mgid->unicast.interface_id) );
+ }
+ else
+ {
+
+ /* a specific MGID was requested so validate the resulting MGID */
+ valid = __validate_requested_mgid(p_rcv, &mcm_rec);
+ if (! valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B22: "
+ "Invalid requested MGID.\n");
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_REQ_INVALID;
+ goto Exit;
+ }
+ }
+
+ /* check the requested parameters are realizable */
+ if (__mgrp_request_is_realizable(p_rcv, comp_mask, &mcm_rec) == FALSE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B26: "
+ "Requested MGRP parameters are not realizable.\n");
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_REQ_INVALID;
+ goto Exit;
+ }
+
+ /* create a new MC Group */
+ *pp_mgrp = osm_mgrp_new(mlid);
+
+ if (*pp_mgrp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B08: "
+ "osm_mgrp_new failed.\n");
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ goto Exit;
+ }
+
+ /* the mcmember_record should have mtu_sel, rate_sel and pkt_lifetime_sel = 2 */
+ (*pp_mgrp)->mcmember_rec.mtu |= 2<<6; /* exactly */
+ (*pp_mgrp)->mcmember_rec.rate |= 2<<6; /* exactly */
+ (*pp_mgrp)->mcmember_rec.pkt_life |= 2<<6; /* exactly */
+
+ /* Initialize the mgrp */
+ (*pp_mgrp)->mcmember_rec = mcm_rec;
+ (*pp_mgrp)->mcmember_rec.mlid = mlid;
+
+ /* Insert the new group in the data base */
+
+ /* since we might have an old group by that mlid
+ one that its deletion was delayed for an idle time
+ we need to deallocate it first */
+ p_prev_mgrp = (osm_mgrp_t *)cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid);
+ if (p_prev_mgrp != (osm_mgrp_t *)cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Found previous group for mlid:0x%04x - Need to destroy it.\n",
+ cl_ntoh16(mlid));
+ cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_prev_mgrp );
+ osm_mgrp_destroy( p_prev_mgrp );
+ }
+
+ cl_qmap_insert(&p_rcv->p_subn->mgrp_mlid_tbl,
+ mlid,
+ &(*pp_mgrp)->map_item);
+
+ /* Send a Report to any InformInfo registerd for
+ Trap 66 : MCGroup create */
+ osm_mgrp_send_create_notice(p_rcv->p_subn, p_rcv->p_log, *pp_mgrp);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return status;
+
+}
+
+/*********************************************************************
+Process a request for leaving the group
+**********************************************************************/
+static void
+osm_mcmr_rcv_leave_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ boolean_t valid;
+ osm_mgrp_t *p_mgrp;
+ ib_api_status_t status;
+ ib_sa_mad_t *p_sa_mad;
+ ib_member_rec_t*p_recvd_mcmember_rec;
+ ib_member_rec_t mcmember_rec;
+ ib_net16_t mlid;
+ ib_net16_t sa_status;
+ ib_net64_t portguid;
+ osm_mcm_port_t *p_mcm_port;
+ uint8_t port_join_state;
+ uint8_t new_join_state;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_leave_mgrp );
+
+ p_mgrp = NULL;
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_mcmember_rec =
+ (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ mcmember_rec = *p_recvd_mcmember_rec;
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+ status = __get_mgrp_by_mgid(p_rcv,p_recvd_mcmember_rec, &p_mgrp);
+ if(status == IB_SUCCESS)
+ {
+ mlid = p_mgrp->mlid;
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ /* check validity of the delete request o15-0.1.14 */
+ valid = __validate_delete(p_rcv,
+ p_mgrp,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ p_recvd_mcmember_rec,
+ &p_mcm_port);
+
+ if (valid)
+ {
+
+ /*
+ * according to the same o15-0.1.14 we get the stored JoinState and the
+ * request JoinState and they must be opposite to leave -
+ * otherwise just update it
+ */
+ port_join_state = p_mcm_port->scope_state & 0x0F;
+ new_join_state =
+ port_join_state & ~(p_recvd_mcmember_rec->scope_state & 0x0F);
+ if (new_join_state)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_leave_mgrp: "
+ "After update JoinState != 0. Updating from 0x%X to 0x%X.\n",
+ port_join_state,
+ new_join_state
+ );
+ /* Just update the result JoinState */
+ p_mcm_port->scope_state =
+ new_join_state | (p_mcm_port->scope_state & 0xf0);
+
+ mcmember_rec.scope_state = p_mcm_port->scope_state;
+ }
+ else
+ {
+ /* we need to return the stored scope state */
+ mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+ /* OK we can leave */
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ status = osm_sm_mcgrp_leave(p_rcv->p_sm,
+ mlid,
+ portguid);
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_leave_mgrp: ERR 1B09: "
+ "osm_sm_mcgrp_leave failed.\n");
+
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+ /* Note: The deletion of the mgrp itself will be done in the callback
+ for the multicast tree updating (osm_mcast_mgr_process_mgrp_cb) */
+ }
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_leave_mgrp: ERR 1B25: "
+ "Received an Invalid Delete Request on "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " for "
+ "PortGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_leave_mgrp: "
+ "Multicast group not present failed.\n");
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /* Send an SA RESPONSE */
+ __osm_mcmr_rcv_respond( p_rcv,
+ p_madw,
+ &mcmember_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+
+}
+
+/**********************************************************************
+ Handle a join (or create) request
+**********************************************************************/
+static
+void
+osm_mcmr_rcv_join_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw
+ )
+{
+ boolean_t valid;
+ osm_mgrp_t *p_mgrp = NULL;
+ ib_api_status_t status;
+ ib_sa_mad_t *p_sa_mad;
+ ib_member_rec_t*p_recvd_mcmember_rec;
+ ib_member_rec_t mcmember_rec;
+ ib_net16_t sa_status;
+ ib_net16_t mlid;
+ osm_mcm_port_t *p_mcmr_port;
+ ib_net64_t portguid;
+ osm_port_t * p_port;
+ osm_physp_t* p_physp;
+ osm_physp_t* p_request_physp;
+ uint8_t is_new_group; /* TRUE = there is a need to create a group */
+ osm_mcast_req_type_t req_type;
+ uint8_t join_state;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_join_mgrp );
+
+ p_mgrp = NULL;
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_mcmember_rec =
+ (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ mcmember_rec = *p_recvd_mcmember_rec;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_join_mgrp: "
+ "Dump of incoming record.\n");
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+ /* make sure the requested port guid is known to the SM */
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ portguid);
+
+ if(p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_join_mgrp: "
+ "Invalid portguid =< 0x%016" PRIx64 ".\n",
+ portguid);
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* Check that the p_physp and the requestor physp are in the same
+ partition. */
+ p_request_physp =
+ osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_request_physp == NULL)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_request_physp))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_join_mgrp: "
+ "port and requestor don't share pkey.\n" );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ ib_member_get_scope_state(
+ p_recvd_mcmember_rec->scope_state, NULL, &join_state);
+
+ /* do we need to create a new group? */
+ status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, &p_mgrp);
+ if((status == IB_NOT_FOUND) || p_mgrp->to_be_deleted)
+ {
+ /* check for JoinState.FullMember = 1 o15.0.1.9 */
+ if ((join_state & 0x01) != 0x01)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_join_mgrp: ERR 1B10: "
+ "Provided Join State != FullMember - required for create, "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ) );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /* check for the comp_mask */
+ valid = __check_create_comp_mask(p_sa_mad->comp_mask,
+ p_recvd_mcmember_rec);
+ if(valid)
+ {
+ status = osm_mcmr_rcv_create_new_mgrp(p_rcv,
+ p_sa_mad->comp_mask,
+ p_recvd_mcmember_rec,
+ &p_mgrp);
+ if(status != IB_SUCCESS)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = status;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+ /* copy the MGID to the result */
+ mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid;
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_join_mgrp: ERR 1B11: "
+ "method = %s,"
+ "scope_state = 0x%x, "
+ "component mask = 0x%016" PRIx64 ", "
+ "expected comp mask = 0x%016" PRIx64 ", "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ ib_get_sa_method_str(p_sa_mad->method),
+ p_recvd_mcmember_rec->scope_state,
+ cl_ntoh64(p_sa_mad->comp_mask),
+ CL_NTOH64(REQUIRED_MC_CREATE_COMP_MASK),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ) );
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = IB_SA_MAD_STATUS_INSUF_COMPS;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+ is_new_group = 1;
+ req_type = OSM_MCAST_REQ_TYPE_CREATE;
+ }
+ else
+ {
+ /* no need for a new group */
+ is_new_group = 0;
+ req_type = OSM_MCAST_REQ_TYPE_JOIN;
+ }
+
+ CL_ASSERT(p_mgrp);
+ mlid = p_mgrp->mlid;
+
+ /*
+ * o15-0.2.4: If SA supports UD multicast, then SA shall cause an
+ * endport to join an existing multicast group if:
+ * 1. It receives a SubnAdmSet() method for a MCMemberRecord, and
+ * - WE KNOW THAT ALREADY
+ * 2. The MGID is specified and matches an existing multicast
+ * group, and
+ * - WE KNOW THAT ALREADY
+ * 3. The MCMemberRecord:JoinState is not all 0s, and
+ * 4. PortGID is specified and
+ * - WE KNOW THAT ALREADY (as it matched a real one)
+ * 5. All other components match that existing group, either by
+ * being wildcarded or by having values identical to those specified
+ * by the component mask and in use by the group with the exception
+ * of components such as ProxyJoin and Reserved, which are ignored
+ * by SA.
+ *
+ * We we need to check #3 and #5 here:
+ */
+ valid = __validate_more_comp_fields(
+ p_rcv->p_log,
+ p_mgrp,
+ p_recvd_mcmember_rec,
+ p_sa_mad->comp_mask) && (join_state != 0);
+
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_join_mgrp: ERR 1B12: "
+ "__validate_more_comp_fields or JoinState = 0 failed, "
+ "sending IB_SA_MAD_STATUS_REQ_INVALID.\n");
+
+ /* since we might have created the new group we need to cleanup */
+ __cleanup_mgrp(p_rcv, mlid);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /*
+ * Do some validation of the modification
+ */
+ if (! is_new_group)
+ {
+ /*
+ * o15-0.2.1 requires validation of the requesting port
+ * in the case of modification:
+ */
+ valid = __validate_modify(p_rcv,
+ p_mgrp,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ p_recvd_mcmember_rec,
+ &p_mcmr_port);
+ if (! valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_join_mgrp: ERR 1B13: "
+ "__validate_modify failed, "
+ "sending IB_SA_MAD_STATUS_REQ_INVALID.\n");
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+ }
+
+ /* create or update existing port (join-state will be updated) */
+ status = __add_new_mgrp_port(
+ p_rcv,
+ p_mgrp,
+ p_recvd_mcmember_rec,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ &p_mcmr_port);
+
+ if(status != IB_SUCCESS)
+ {
+ /* we fail to add the port so we might need to delete the
+ group */
+ __cleanup_mgrp(p_rcv, mlid);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /* o15.0.1.11: copy the join state */
+ mcmember_rec.scope_state = p_mcmr_port->scope_state;
+
+ /* copy qkey mlid tclass pkey sl_flow_hop mtu rate pkt_life sl_flow_hop */
+ __copy_from_create_mc_rec(&mcmember_rec, &p_mgrp->mcmember_rec);
+
+ /* Release the lock as we don't need it. */
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /* do the actual routing (actually schedule the update) */
+ status =
+ osm_sm_mcgrp_join(p_rcv->p_sm,
+ mlid,
+ p_recvd_mcmember_rec->port_gid.unicast.interface_id,
+ req_type );
+
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_join_mgrp: ERR 1B14: "
+ "osm_sm_mcgrp_join failed, "
+ "sending IB_SA_MAD_STATUS_NO_RESOURCES.\n");
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+ /* the request for routing failed so we need to remove the port */
+ p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+ if(p_mgrp != NULL)
+ {
+ osm_mgrp_remove_port(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_mgrp,
+ p_recvd_mcmember_rec->port_gid.unicast.interface_id);
+ __cleanup_mgrp(p_rcv, mlid);
+ }
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+
+ } /* failed to route */
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+
+ __osm_mcmr_rcv_respond( p_rcv,
+ p_madw,
+ &mcmember_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+
+}
+
+/**********************************************************************
+ Add a patched multicast group to the results list
+**********************************************************************/
+static ib_api_status_t
+__osm_mcmr_rcv_new_mcmr(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const ib_member_rec_t* p_rcvd_rec,
+ IN cl_qlist_t* const p_list)
+{
+ osm_mcmr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_new_mcmr );
+
+ p_rec_item = (osm_mcmr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_new_mcmr: ERR 1B15: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+ /* HACK: Not trusted requestors should result with 0 Join
+ State, Port Guid, and Proxy */
+ p_rec_item->rec = *p_rcvd_rec;
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ Match the given mgrp to the requested mcmr
+**********************************************************************/
+void
+__osm_sa_mcm_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_mgrp_t * const p_mgrp = (osm_mgrp_t *)p_map_item;
+ osm_sa_mcmr_search_ctxt_t* const p_ctxt =
+ (osm_sa_mcmr_search_ctxt_t *)context;
+ osm_mcmr_recv_t* const p_rcv = p_ctxt->p_rcv;
+ const ib_member_rec_t* p_rcvd_rec = p_ctxt->p_mcmember_rec;
+ const osm_physp_t* p_req_physp = p_ctxt->p_req_physp;
+
+ /* since we might change scope_state */
+ ib_member_rec_t match_rec;
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ osm_mcm_port_t* p_mcm_port;
+ ib_net64_t portguid = p_rcvd_rec->port_gid.unicast.interface_id;
+ /* will be used for group or port info */
+ uint8_t scope_state;
+ uint8_t scope_state_mask = 0;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_mcm_by_comp_mask_cb );
+
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "Checking mlid:0x%X\n",
+ cl_ntoh16(p_mgrp->mlid ));
+
+ /* the group might be marked for deletion */
+ if (p_mgrp->to_be_deleted)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "Group mlid:0x%X is marked to be deleted.\n",
+ cl_ntoh16(p_mgrp->mlid ));
+ goto Exit;
+ }
+
+ /* first try to eliminate the group by MGID, MLID, or P_Key */
+ if ((IB_MCR_COMPMASK_MGID & comp_mask) &&
+ cl_memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t))) {
+ goto Exit;
+ }
+
+ if ((IB_MCR_COMPMASK_MLID & comp_mask) &&
+ cl_memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t))) {
+ goto Exit;
+ }
+
+ /* if the requestor physical port doesn't have the pkey that is defined for the
+ group - exit. */
+ if (! osm_physp_has_pkey( p_rcv->p_log, p_mgrp->mcmember_rec.pkey, p_req_physp ))
+ goto Exit;
+
+ /*
+ * o15-0.1.16: If SA supports UD multicast, then if it receives a
+ * SubnAdmGetTable() of MCMemberRecord with the MCMemberRecord:PortGID
+ * wildcarded, then SA shall return a single MCMemberRecord for each
+ * multicast group that matches the query operation.
+ */
+
+ /* so did we got the PortGUID mask */
+ if (IB_MCR_COMPMASK_PORT_GID & comp_mask)
+ {
+ /* try to find this port */
+ if (! osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port))
+ {
+ scope_state = p_mcm_port->scope_state;
+ }
+ else
+ {
+ /* port not in group */
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* point to the group information */
+ scope_state = p_mgrp->mcmember_rec.scope_state;
+ }
+
+ /* now do the rest of the match */
+ if ((IB_MCR_COMPMASK_QKEY & comp_mask) &&
+ (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey)) goto Exit;
+
+ if ((IB_MCR_COMPMASK_PKEY & comp_mask) &&
+ (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey)) goto Exit;
+
+ if ((IB_MCR_COMPMASK_TCLASS & comp_mask) &&
+ (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass)) goto Exit;
+
+ /* check SL , Flow and Hop limit */
+ {
+ uint8_t mgrp_sl, query_sl;
+ uint32_t mgrp_flow, query_flow;
+ uint8_t mgrp_hop, query_hop;
+
+ ib_member_get_sl_flow_hop(p_rcvd_rec->sl_flow_hop,
+ &query_sl, &query_flow, &query_hop);
+
+ ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+ &mgrp_sl, &mgrp_flow, &mgrp_hop);
+
+ if (IB_MCR_COMPMASK_SL & comp_mask )
+ if (query_sl != mgrp_sl) goto Exit;
+
+ if (IB_MCR_COMPMASK_FLOW & comp_mask)
+ if (query_flow != mgrp_flow) goto Exit;
+
+ if (IB_MCR_COMPMASK_HOP & comp_mask)
+ if (query_hop != mgrp_hop) goto Exit;
+ }
+
+ if (IB_MCR_COMPMASK_SCOPE & comp_mask)
+ scope_state_mask = 0xF0;
+
+ if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask)
+ scope_state_mask = scope_state_mask | 0x0F;
+
+ if ((scope_state_mask & p_rcvd_rec->scope_state) !=
+ (scope_state_mask & scope_state)) goto Exit;
+
+ if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
+ (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join)) goto Exit;
+
+ /* need to validate mtu, rate, and pkt_lifetime fields. */
+ if (__validate_more_comp_fields( p_rcv->p_log,
+ p_mgrp,
+ p_rcvd_rec,
+ comp_mask ) == FALSE) goto Exit;
+
+ /* add to the list */
+ match_rec = p_mgrp->mcmember_rec;
+ match_rec.scope_state = scope_state;
+
+ __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Handle a query request
+**********************************************************************/
+void
+osm_mcmr_query_mgrp(IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw) {
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_member_rec_t* p_rcvd_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_member_rec_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_sa_mcmr_search_ctxt_t context;
+ osm_mcmr_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+ boolean_t trusted_req = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_query_mgrp );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+ comp_mask = p_rcvd_mad->comp_mask;
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_query_mgrp: ERR 1B04: "
+ "Cannot find requestor physical port.\n" );
+ goto Exit;
+ }
+
+ cl_qlist_init( &rec_list );
+
+ context.p_mcmember_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ CL_PLOCK_ACQUIRE( p_rcv->p_lock );
+
+ /* simply go over all MCGs and match */
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+ __osm_sa_mcm_by_comp_mask_cb,
+ &context);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_query_mgrp: ERR 1B05: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_mcmr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_member_rec_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_mcmr_query_mgrp: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_query_mgrp: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_member_rec_t) + IB_SA_MAD_HDR_SIZE,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_query_mgrp: ERR 1B16: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_member_rec_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ /*
+ p819 - The PortGID, JoinState and ProxyJoin shall be zero,
+ except in the case of a trusted request.
+ Note: In the mad controller we check that the SM_Key received on
+ the mad is valid. Meaning - is either zero or equal to the local
+ sm_key.
+ */
+ if (p_resp_sa_mad->sm_key == 0)
+ trusted_req = FALSE;
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ if (trusted_req == FALSE)
+ {
+ cl_memclr(&p_resp_rec->port_gid, sizeof(ib_gid_t));
+ ib_member_set_join_state(p_resp_rec, 0);
+ p_resp_rec->proxy_join = 0;
+ }
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_query_mgrp: ERR 1B17: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_process(
+ IN osm_mcmr_recv_t* const p_rcv,
+ const IN osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ ib_member_rec_t *p_recvd_mcmember_rec;
+ boolean_t valid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_mcmember_rec =
+ (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ switch (p_sa_mad->method)
+ {
+ case IB_MAD_METHOD_SET:
+ valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: ERR 1B18: "
+ "component mask = 0x%016" PRIx64 ", "
+ "expected comp mask = 0x%016" PRIx64 " ,"
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " for "
+ "PortGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sa_mad->comp_mask),
+ CL_NTOH64(JOIN_MC_COMP_MASK),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /*
+ * Join or Create Multicast Group
+ */
+ osm_mcmr_rcv_join_mgrp(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_DELETE:
+ valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: ERR 1B20: "
+ "component mask = 0x%016" PRIx64 ", "
+ "expected comp mask = 0x%016" PRIx64 ".\n",
+ cl_ntoh64(p_sa_mad->comp_mask),
+ CL_NTOH64(JOIN_MC_COMP_MASK));
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /*
+ * Leave Multicast Group
+ */
+ osm_mcmr_rcv_leave_mgrp(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_GET:
+ case IB_MAD_METHOD_GETTABLE:
+ /*
+ * Querying a Multicast Group
+ */
+ osm_mcmr_query_mgrp(p_rcv, p_madw);
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: ERR 1B21: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ break;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcmr_rcv_ctrl_t.
+ * This object represents the Multicast member record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mcmr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mcmr_rcv_process( ((osm_mcmr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_construct(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_destroy(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_ctrl_init(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mcmr_rcv_ctrl_init );
+
+ osm_mcmr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MCMEMBER_RECORD,
+ __osm_mcmr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_ctrl_init: ERR 1C01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nr_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_node_record.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_NR_RCV_POOL_MIN_SIZE 32
+#define OSM_NR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_nr_item
+{
+ cl_pool_item_t pool_item;
+ ib_node_record_t rec;
+
+} osm_nr_item_t;
+
+typedef struct _osm_nr_search_ctxt
+{
+ const ib_node_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ cl_qlist_t* p_list;
+ osm_nr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+
+} osm_nr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_construct(
+ IN osm_nr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_destroy(
+ IN osm_nr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_init(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_nr_rcv_init );
+
+ osm_nr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_NR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_NR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_nr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_nr_rcv_new_nr(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const port_guid,
+ IN ib_net16_t const lid )
+{
+ osm_nr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_new_nr );
+
+ p_rec_item = (osm_nr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_new_nr: ERR 1D02: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_new_nr: "
+ "New NodeRecord: node 0x%016" PRIx64
+ "\n\t\t\t\tport 0x%016" PRIx64 ", lid 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ cl_ntoh64( port_guid ), cl_ntoh16( lid )
+ );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof(ib_node_record_t) );
+
+ p_rec_item->rec.lid = lid;
+
+ p_rec_item->rec.node_info = p_node->node_info;
+ p_rec_item->rec.node_info.port_guid = port_guid;
+ cl_memcpy(&(p_rec_item->rec.node_desc), &(p_node->node_desc),
+ IB_NODE_DESCRIPTION_SIZE);
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_create_nr(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const match_port_guid,
+ IN ib_net16_t const match_lid,
+ IN const osm_physp_t* const p_req_physp )
+{
+ const osm_physp_t* p_physp;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint16_t match_lid_ho;
+ uint16_t lid_ho;
+ ib_net16_t base_lid_ho;
+ ib_net16_t max_lid_ho;
+ uint8_t lmc;
+ ib_net64_t port_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_create_nr );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_create_nr: "
+ "Looking for NodeRecord with LID: 0x%X GUID:0x%016" PRIx64 "\n",
+ cl_ntoh16( match_lid ),
+ cl_ntoh64( match_port_guid )
+ );
+ }
+
+ /*
+ For switches, do not return the NodeInfo record
+ for each port on the switch, just port 0.
+ */
+ if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ num_ports = 1;
+ else
+ num_ports = osm_node_get_num_physp( p_node );
+
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* Check to see if the found p_physp and the requestor physp
+ share a pkey. If not - continue */
+ if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_req_physp ) )
+ continue;
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ if( match_port_guid && ( port_guid != match_port_guid ) )
+ continue;
+
+ base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) );
+ lmc = osm_physp_get_lmc( p_physp );
+ max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+ match_lid_ho = cl_ntoh16( match_lid );
+
+ if( match_lid_ho )
+ {
+ /*
+ We validate that the lid belongs to this node.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_create_nr: "
+ "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+ cl_ntoh16( base_lid_ho ),
+ cl_ntoh16( match_lid_ho ),
+ cl_ntoh16( max_lid_ho )
+ );
+ }
+
+ if( (match_lid_ho <= max_lid_ho) && (match_lid_ho >= base_lid_ho) )
+ {
+ /*
+ Ignore return code for now.
+ */
+ __osm_nr_rcv_new_nr( p_rcv, p_node, p_list,
+ port_guid, match_lid );
+ }
+ }
+ else
+ {
+ /*
+ For every lid value create a Node Record.
+ */
+ for( lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ status = __osm_nr_rcv_new_nr( p_rcv, p_node, p_list,
+ port_guid, cl_hton16( lid_ho ) );
+ if( status != IB_SUCCESS )
+ break;
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+void
+__osm_nr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_nr_search_ctxt_t* const p_ctxt = (osm_nr_search_ctxt_t *)context;
+ const osm_node_t* const p_node = (osm_node_t*)p_map_item;
+ const ib_node_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp;
+ osm_nr_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ ib_net64_t const comp_mask = p_ctxt->comp_mask;
+ ib_net64_t match_port_guid = 0;
+ ib_net16_t match_lid = 0;
+
+ OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_nr_rcv_by_comp_mask );
+
+ osm_dump_node_info(
+ p_ctxt->p_rcv->p_log,
+ & p_node->node_info,
+ OSM_LOG_VERBOSE );
+
+ if( comp_mask & IB_NR_COMPMASK_LID )
+ match_lid = p_rcvd_rec->lid;
+
+ if( comp_mask & IB_NR_COMPMASK_NODEGUID)
+ {
+ /*
+ DEBUG TOP
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_by_comp_mask: "
+ "Looking for node 0x%016" PRIx64
+ ", found 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_rcvd_rec->node_info.node_guid ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) )
+ );
+ }
+ /*
+ DEBUG BOTTOM
+ */
+ if( (p_node->node_info.node_guid != p_rcvd_rec->node_info.node_guid ))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_PORTGUID)
+ {
+ match_port_guid = p_rcvd_rec->node_info.port_guid;
+ }
+ if( comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID)
+ {
+ if( (p_node->node_info.sys_guid != p_rcvd_rec->node_info.sys_guid))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_BASEVERSION )
+ {
+ if( (p_node->node_info.base_version != p_rcvd_rec->node_info.base_version))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_CLASSVERSION)
+ {
+ if( (p_node->node_info.class_version != p_rcvd_rec->node_info.class_version))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_NODETYPE)
+ {
+ if( (p_node->node_info.node_type != p_rcvd_rec->node_info.node_type))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_NUMPORTS)
+ {
+ if( (p_node->node_info.num_ports != p_rcvd_rec->node_info.num_ports))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_PARTCAP)
+ {
+ if( (p_node->node_info.partition_cap != p_rcvd_rec->node_info.partition_cap))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_DEVID)
+ {
+ if( (p_node->node_info.device_id != p_rcvd_rec->node_info.device_id))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_REV)
+ {
+ if( (p_node->node_info.revision != p_rcvd_rec->node_info.revision))
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_PORTNUM)
+ {
+ if( ib_node_info_get_local_port_num(&p_node->node_info) !=
+ ib_node_info_get_local_port_num(&p_rcvd_rec->node_info) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_VENDID)
+ {
+ if( ib_node_info_get_vendor_id(&p_node->node_info) !=
+ ib_node_info_get_vendor_id(&p_rcvd_rec->node_info) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_NODEDESC)
+ {
+ if( strncmp((char*) &p_node->node_desc,
+ (char*) &p_rcvd_rec->node_desc, sizeof(ib_node_desc_t)))
+ goto Exit;
+ }
+
+ __osm_nr_rcv_create_nr( p_rcv, p_node, p_ctxt->p_list,
+ match_port_guid, match_lid, p_req_physp);
+
+ Exit:
+ OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_process(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_node_record_t* p_rcvd_rec;
+ ib_node_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_nr_search_ctxt_t context;
+ osm_nr_item_t* p_rec_item;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D04: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D05: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ cl_qlist_init( &rec_list );
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl,
+ __osm_nr_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_nr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_node_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_nr_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_nr_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_node_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D06: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_node_record_t) );
+
+ p_resp_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D07: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nr_rcv_ctrl_t.
+ * This object represents the Node Record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nr_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_nr_rcv_process( ((osm_nr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_construct(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_destroy(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_ctrl_init(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl,
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_nr_rcv_ctrl_init );
+
+ osm_nr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_RECORD,
+ __osm_nr_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_ctrl_init: ERR 1E01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pr_rcv_t.
+ * This object represents the PathRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_path_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_multicast.h>
+
+#define OSM_PR_RCV_POOL_MIN_SIZE 64
+#define OSM_PR_RCV_POOL_GROW_SIZE 64
+
+typedef struct _osm_pr_item
+{
+ cl_pool_item_t pool_item;
+ ib_path_rec_t path_rec;
+
+} osm_pr_item_t;
+
+typedef struct _osm_path_parms
+{
+ ib_net16_t pkey;
+ uint8_t mtu;
+ uint8_t rate;
+ uint8_t sl;
+ uint8_t pkt_life;
+ boolean_t reversible;
+} osm_path_parms_t;
+
+typedef struct osm_sa_pr_mcmr_search_ctxt {
+ ib_gid_t *p_mgid;
+ osm_mgrp_t *p_mgrp;
+ osm_pr_rcv_t *p_rcv;
+} osm_sa_pr_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_construct(
+ IN osm_pr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_destroy(
+ IN osm_pr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pr_pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pr_rcv_init(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_pr_rcv_init );
+
+ osm_pr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pr_pool,
+ OSM_PR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_PR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_pr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_rcv_get_path_parms(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const uint16_t dest_lid_ho,
+ IN const ib_net64_t comp_mask,
+ OUT osm_path_parms_t* const p_parms )
+{
+ ib_net64_t node_guid;
+ const osm_node_t* p_node;
+ const osm_physp_t* p_physp;
+ const osm_physp_t* p_dest_physp;
+ const osm_switch_t* p_sw;
+ const ib_port_info_t* p_pi;
+ const cl_qmap_t* p_sw_tbl;
+
+ ib_api_status_t status = IB_SUCCESS;
+ uint8_t mtu;
+ uint8_t rate;
+ uint8_t required_mtu;
+ uint8_t required_rate;
+ ib_net16_t dest_lid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_path_parms );
+
+ dest_lid = cl_hton16( dest_lid_ho );
+
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+ p_physp = osm_port_get_default_phys_ptr( p_src_port );
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+ p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ rate = ib_port_info_compute_rate( p_pi );
+
+ /*
+ Walk the subnet object from source to destination,
+ tracking the most restrictive rate and mtu values along the way...
+
+ If source port node is a switch, then p_physp should
+ point to the port that routes the destination lid
+ */
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+
+ if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ {
+ p_sw = (osm_switch_t *)cl_qmap_get( p_sw_tbl,
+ osm_node_get_node_guid( p_node ) );
+
+ if( p_sw == (osm_switch_t *)cl_qmap_end( p_sw_tbl ) )
+ {
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * If the dest_lid_ho is equal to the lid of the switch pointed by
+ * p_sw then p_physp will be the physical port of the switch port zero.
+ */
+
+ p_physp = osm_switch_get_route_by_lid(p_sw, cl_ntoh16(dest_lid_ho) );
+ if ( p_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F02: "
+ "Cannot find routing to lid:0x%X from switch for guid 0x%016" PRIx64 ".\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+ /*
+ * Same as above..
+ */
+
+ p_node = osm_physp_get_node_ptr(p_dest_physp);
+
+ if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ {
+ p_sw = (osm_switch_t *)cl_qmap_get( p_sw_tbl,
+ osm_node_get_node_guid(p_node));
+
+ if( p_sw == (osm_switch_t *)cl_qmap_end( p_sw_tbl ) )
+ {
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_dest_physp = osm_switch_get_route_by_lid( p_sw,
+ cl_ntoh16(dest_lid_ho) );
+
+ if ( p_dest_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F03: "
+ "Cannot find routing to lid:0x%X from switch for guid 0x%016" PRIx64 ".\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ }
+
+ while( p_physp != p_dest_physp )
+ {
+ p_physp = osm_physp_get_remote( p_physp );
+
+ if ( p_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F05: "
+ "Cannot find remote phys port when routing to lid:0x%X from node guid 0x%016" PRIx64 ".\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ This is point to point case (no switch in between)
+ */
+
+ if( p_physp == p_dest_physp )
+ break;
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+
+ if( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+ {
+ /*
+ There is some sort of problem in the subnet object!
+ If this isn't a switch, we should have reached
+ the destination by now!
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F06: "
+ "Internal error, bad path.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ node_guid = osm_node_get_node_guid( p_node );
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ /*
+ There is some sort of problem in the subnet object!
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F04: "
+ "Internal error, no switch for guid 0x%016" PRIx64 ".\n",
+ cl_ntoh64( node_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ Check parameters for the ingress port in this switch.
+ */
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64 ".\n",
+ mtu,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ if( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+
+ rate = ib_port_info_compute_rate( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest rate = %u at intervening port 0x%016" PRIx64 ".\n",
+ rate,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ /*
+ Continue with the egress port on this switch.
+ */
+ p_physp = osm_switch_get_route_by_lid( p_sw, dest_lid );
+
+ if ( p_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_path_parms: ERR 1F07: "
+ "Dead end on path to lid:0x%X from switch for guid 0x%016" PRIx64 ".\n",
+ dest_lid_ho,
+ cl_ntoh64( node_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64 ".\n",
+ mtu,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ if( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+
+ rate = ib_port_info_compute_rate( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest rate = %u at intervening port 0x%016" PRIx64 ".\n",
+ rate,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ }
+
+ /*
+ p_physp now points to the destination
+ */
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest MTU = %u at destination port 0x%016" PRIx64 ".\n",
+ mtu,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ if( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+
+ rate = ib_port_info_compute_rate( p_pi );
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "New smallest rate = %u at destination port 0x%016" PRIx64 ".\n",
+ rate,
+ osm_physp_get_port_guid( p_physp ) );
+ }
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_path_parms: "
+ "Path min MTU = %u, min rate = %u.\n", mtu, rate );
+ }
+
+ /*
+ Determine if these values meet the user criteria
+ */
+
+ /* we silently ignore cases where only the MTU selector is defined */
+ if ((comp_mask & IB_PR_COMPMASK_MTUSELEC) &&
+ (comp_mask & IB_PR_COMPMASK_MTU))
+ {
+ required_mtu = ib_path_rec_mtu( p_pr );
+ switch( ib_path_rec_mtu_sel( p_pr ) )
+ {
+ case 0: /* must be greater than */
+ if( mtu <= required_mtu )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 1: /* must be less than */
+ if( mtu >= required_mtu )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 2: /* exact match */
+ if( mtu != required_mtu )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 3: /* largest available */
+ /* can't be disqualified by this one */
+ break;
+
+ default:
+ /* if we're here, there's a bug in ib_path_rec_mtu_sel() */
+ CL_ASSERT( FALSE );
+ status = IB_ERROR;
+ break;
+ }
+ }
+
+ /* we silently ignore cases where only the Rate selector is defined */
+ if ((comp_mask & IB_PR_COMPMASK_RATESELEC) &&
+ (comp_mask & IB_PR_COMPMASK_RATE))
+ {
+ required_rate = ib_path_rec_rate( p_pr );
+ switch( ib_path_rec_rate_sel( p_pr ) )
+ {
+ case 0: /* must be greater than */
+ if( rate <= required_rate )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 1: /* must be less than */
+ if( rate >= required_rate )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 2: /* exact match */
+ if( rate != required_rate )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 3: /* largest available */
+ /* can't be disqualified by this one */
+ break;
+
+ default:
+ /* if we're here, there's a bug in ib_path_rec_mtu_sel() */
+ CL_ASSERT( FALSE );
+ status = IB_ERROR;
+ break;
+ }
+ }
+
+ p_parms->mtu = mtu;
+ p_parms->rate = rate;
+ p_parms->pkey = IB_DEFAULT_PKEY;
+ p_parms->pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+ p_parms->sl = OSM_DEFAULT_SL;
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_build_pr(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const uint16_t src_lid_ho,
+ IN const uint16_t dest_lid_ho,
+ IN const uint8_t preference,
+ IN const osm_path_parms_t* const p_parms,
+ OUT ib_path_rec_t* const p_pr )
+{
+ const osm_physp_t* p_src_physp;
+ const osm_physp_t* p_dest_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_build_pr );
+
+ p_src_physp = osm_port_get_default_phys_ptr( p_src_port );
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+
+ p_pr->dgid.unicast.prefix =
+ osm_physp_get_subnet_prefix( p_dest_physp );
+ p_pr->dgid.unicast.interface_id =
+ osm_physp_get_port_guid( p_dest_physp );
+
+ p_pr->sgid.unicast.prefix =
+ osm_physp_get_subnet_prefix( p_src_physp );
+ p_pr->sgid.unicast.interface_id =
+ osm_physp_get_port_guid( p_src_physp );
+
+ p_pr->dlid = cl_hton16( dest_lid_ho );
+ p_pr->slid = cl_hton16( src_lid_ho );
+
+ p_pr->pkey = p_parms->pkey;
+ p_pr->sl = p_parms->sl;
+ p_pr->mtu = (uint8_t)(p_parms->mtu | 0x80);
+ p_pr->rate = (uint8_t)(p_parms->rate | 0x80);
+
+ /* According to spec definition Table 171 PacketLifeTime description,
+ for loopback paths, packetLifeTime shall be zero. */
+ if ( p_src_port == p_dest_port )
+ /* This is loopback */
+ p_pr->pkt_life = 0x80;
+ else
+ p_pr->pkt_life = (uint8_t)(p_parms->pkt_life | 0x80);
+
+ p_pr->preference = preference;
+
+ /* always return num_path = 0: so this is only the reversible */
+ if (p_parms->reversible) p_pr->num_path = 0x80;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+
+/**********************************************************************
+ **********************************************************************/
+static osm_pr_item_t*
+__osm_pr_rcv_get_lid_pair_path(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const uint16_t src_lid_ho,
+ IN const uint16_t dest_lid_ho,
+ IN const ib_net64_t comp_mask,
+ IN const uint8_t preference )
+{
+ osm_path_parms_t path_parms;
+ osm_path_parms_t rev_path_parms;
+ osm_pr_item_t *p_pr_item;
+ ib_api_status_t status, rev_path_status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_lid_pair_path );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_lid_pair_path: "
+ "Src LID 0x%X, Dest LID 0x%X.\n",
+ src_lid_ho, dest_lid_ho );
+ }
+
+ p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );
+ if( p_pr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_get_lid_pair_path: ERR 1F01: "
+ "Unable to allocate path record.\n" );
+ goto Exit;
+ }
+
+ status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, p_src_port,
+ p_dest_port, dest_lid_ho, comp_mask, &path_parms );
+
+ if( status != IB_SUCCESS )
+ {
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_pr_item = NULL;
+ goto Exit;
+ }
+
+ /* now try the reversible path */
+ rev_path_status =
+ __osm_pr_rcv_get_path_parms(
+ p_rcv, p_pr, p_dest_port,
+ p_src_port, src_lid_ho, comp_mask, &rev_path_parms );
+ path_parms.reversible = (rev_path_status == IB_SUCCESS);
+
+ /* did we get a Reversible Path compmask ? */
+ /*
+ NOTE that if the reversible component = 0, it is a don't care
+ rather then requiring non-reversible paths ...
+ see Vol1 Ver1.2 p900 l16
+ */
+ if (comp_mask & IB_PR_COMPMASK_REVERSIBLE)
+ if ( (! path_parms.reversible && (p_pr->num_path & 0x80)))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_lid_pair_path: "
+ "Requested reversible path but failed to get one.\n");
+
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_pr_item = NULL;
+ goto Exit;
+ };
+
+ __osm_pr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho,
+ dest_lid_ho, preference, &path_parms,
+ &p_pr_item->path_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( p_pr_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_get_port_pair_paths(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const p_req_port,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ osm_pr_item_t* p_pr_item;
+ uint16_t src_lid_min_ho;
+ uint16_t src_lid_max_ho;
+ uint16_t dest_lid_min_ho;
+ uint16_t dest_lid_max_ho;
+ uint16_t src_lid_ho;
+ uint16_t dest_lid_ho;
+ uint32_t path_num;
+ uint8_t preference;
+ uintn_t iterations;
+ uintn_t src_offset;
+ uintn_t dest_offset;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_port_pair_paths );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_port_pair_paths: "
+ "Src port 0x%016" PRIx64 ", "
+ "Dst port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_port_get_guid( p_src_port ) ),
+ cl_ntoh64( osm_port_get_guid( p_dest_port ) ) );
+ }
+
+ /* Check that the req_port, src_port and dest_port all share a
+ pkey. The check is done on the default physical port of the ports */
+ if (osm_port_share_pkey(p_rcv->p_log, p_req_port, p_src_port) == FALSE ||
+ osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port) == FALSE ||
+ osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port) == FALSE )
+ {
+ /* One of the pairs don't share a pkey - the path is disqualified.
+ Exit */
+ goto Exit;
+ }
+
+ /*
+ We shouldn't be here if the paths are disqualified in some way...
+ Thus, we assume every possible connection is valid.
+
+ We desire to return high-quality paths first.
+ In OpenSM, higher quality mean least overlap with other paths.
+ This is acheived in practice by returning paths with
+ different LID value on each end, which means these
+ paths are more redundent that paths with the same LID repeated
+ on one side. For example, in OpenSM the paths between two
+ endpoints with LMC = 1 might be as follows:
+
+ Port A, LID 1 <-> Port B, LID 3
+ Port A, LID 1 <-> Port B, LID 4
+ Port A, LID 2 <-> Port B, LID 3
+ Port A, LID 2 <-> Port B, LID 4
+
+ The OpenSM unicast routing algorithms attempt to dispurse each path
+ to as varied a physical path as is reasonable. 1<->3 and 1<->4 have
+ more physical overlap (hence less redundancy) than 1<->3 and 2<->4.
+
+ OpenSM ranks paths in three preference groups:
+
+ Preference Value Description
+ ---------------- -------------------------------------------
+ 0 Redundant in both directions with other
+ pref value = 0 paths
+
+ 1 Redundant in one direction with other
+ pref value = 0 and pref value = 1 paths.
+
+ 2 Not redundant in either direction with
+ other paths.
+
+ 3-FF Unused
+
+
+ SA clients don't need to know these details, only that the lower
+ preference paths are preferred, as stated in the spec. The paths
+ may not actually be physically redundant depending on the topology
+ of the subnet, but the point of LMC > 0 is to offer redundancy,
+ so I assume the subnet is physically appropriate for the specified
+ LMC value. A more advanced implementation could inspect for physical
+ redundancy, but I'm not going to bother with that now.
+ */
+
+ /*
+ Refine our search if the client specified end-point LIDs
+ */
+ if( comp_mask & IB_PR_COMPMASK_DLID )
+ {
+ dest_lid_min_ho = cl_ntoh16( p_pr->dlid );
+ dest_lid_max_ho = cl_ntoh16( p_pr->dlid );
+ }
+ else
+ {
+ osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho,
+ &dest_lid_max_ho );
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_SLID )
+ {
+ src_lid_min_ho = cl_ntoh16( p_pr->slid );
+ src_lid_max_ho = cl_ntoh16( p_pr->slid );
+ }
+ else
+ {
+ osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho,
+ &src_lid_max_ho );
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_get_port_pair_paths: "
+ "Src LIDs [0x%X,0x%X], "
+ "Dest LIDs [0x%X,0x%X].\n",
+ src_lid_min_ho, src_lid_max_ho,
+ dest_lid_min_ho, dest_lid_max_ho );
+ }
+
+ src_lid_ho = src_lid_min_ho;
+ dest_lid_ho = dest_lid_min_ho;
+
+ /*
+ Preferred paths come first in OpenSM.
+ */
+ preference = 0;
+ path_num = 0;
+
+ if( comp_mask & IB_PR_COMPMASK_NUMBPATH )
+ iterations = p_pr->num_path & 0x7F;
+ else
+ iterations = (uintn_t)(-1);
+
+ while( path_num < iterations )
+ {
+ /*
+ These paths are "fully redundant"
+ */
+
+ p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,
+ p_src_port, p_dest_port, src_lid_ho, dest_lid_ho,
+ comp_mask, preference );
+
+ if( p_pr_item )
+ {
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&p_pr_item->pool_item );
+ ++path_num;
+ }
+
+ if( ++src_lid_ho > src_lid_max_ho )
+ break;
+
+ if( ++dest_lid_ho > dest_lid_max_ho )
+ break;
+ }
+
+ /*
+ Check if we've accumulated all the user cares to see.
+ */
+ if( path_num == iterations )
+ goto Exit;
+
+ /*
+ Don't bother reporting preference 1 paths for now.
+ It's more trouble than it's worth and can only occur
+ if ports have different LMC values, which isn't supported
+ by OpenSM right now anyway.
+ */
+ preference = 2;
+ src_lid_ho = src_lid_min_ho;
+ dest_lid_ho = dest_lid_min_ho;
+ src_offset = 0;
+ dest_offset = 0;
+
+ /*
+ Iterate over the remaining paths.
+ */
+ while( path_num < iterations )
+ {
+ dest_offset++;
+ dest_lid_ho++;
+
+ if( dest_lid_ho > dest_lid_max_ho )
+ {
+ src_offset++;
+ src_lid_ho++;
+
+ if( src_lid_ho > src_lid_max_ho )
+ break; /* done */
+
+ dest_offset = 0;
+ dest_lid_ho = dest_lid_min_ho;
+ }
+
+ /*
+ These paths are "fully non-redundant" with paths already
+ identified above and consequently not of much value.
+
+ Don't return paths we already identified above, as indicated
+ by the offset values being equal.
+ */
+ if( src_offset == dest_offset )
+ continue; /* already reported */
+
+ p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,
+ p_src_port, p_dest_port, src_lid_ho, dest_lid_ho,
+ comp_mask, preference );
+
+ if( p_pr_item )
+ {
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&p_pr_item->pool_item );
+ ++path_num;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_pr_rcv_get_end_points(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ OUT const osm_port_t** const pp_src_port,
+ OUT const osm_port_t** const pp_dest_port )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ ib_api_status_t status;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_end_points );
+
+ /*
+ Determine what fields are valid and then get a pointer
+ to the source and destination port objects, if possible.
+ */
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ /*
+ Check a few easy disqualifying cases up front before getting
+ into the endpoints.
+ */
+
+ if( comp_mask & IB_PR_COMPMASK_PKEY )
+ {
+ if( p_pr->pkey != IB_DEFAULT_PKEY )
+ {
+ if ( p_sa_mad->method == IB_MAD_METHOD_GET )
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ *pp_src_port = 0;
+ *pp_dest_port = 0;
+ goto Exit;
+ }
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_SL )
+ {
+ if( p_pr->sl != OSM_DEFAULT_SL )
+ {
+ if ( p_sa_mad->method == IB_MAD_METHOD_GET )
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ *pp_src_port = 0;
+ *pp_dest_port = 0;
+ goto Exit;
+ }
+ }
+
+ if( p_sa_mad->comp_mask & IB_PR_COMPMASK_SGID )
+ {
+ *pp_src_port = (osm_port_t*)cl_qmap_get(
+ &p_rcv->p_subn->port_guid_tbl,
+ p_pr->sgid.unicast.interface_id );
+
+ if( *pp_src_port == (osm_port_t*)cl_qmap_end(
+ &p_rcv->p_subn->port_guid_tbl ) )
+ {
+ /*
+ This 'error' is the client's fault (bad gid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pr_rcv_get_end_points: "
+ "No source port with GUID = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_pr->sgid.unicast.interface_id) );
+
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+ goto Exit;
+ }
+ }
+ else
+ {
+ *pp_src_port = 0;
+ if( p_sa_mad->comp_mask & IB_PR_COMPMASK_SLID )
+ {
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+ cl_ntoh16(p_pr->slid), (void**)pp_src_port );
+
+ if( ( (status != CL_SUCCESS) || (*pp_src_port == NULL) ) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ /*
+ This 'error' is the client's fault (bad lid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pr_rcv_get_end_points: "
+ "No source port with LID = 0x%X.\n",
+ cl_ntoh16( p_pr->slid) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+ }
+
+ if( p_sa_mad->comp_mask & IB_PR_COMPMASK_DGID )
+ {
+ *pp_dest_port = (osm_port_t*)cl_qmap_get(
+ &p_rcv->p_subn->port_guid_tbl,
+ p_pr->dgid.unicast.interface_id );
+
+ if( *pp_dest_port == (osm_port_t*)cl_qmap_end(
+ &p_rcv->p_subn->port_guid_tbl ) )
+ {
+ /*
+ This 'error' is the client's fault (bad gid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pr_rcv_get_end_points: "
+ "No dest port with GUID = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_pr->dgid.unicast.interface_id) );
+
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+ goto Exit;
+ }
+ }
+ else
+ {
+ *pp_dest_port = 0;
+ if( p_sa_mad->comp_mask & IB_PR_COMPMASK_DLID )
+ {
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+ cl_ntoh16(p_pr->dlid), (void**)pp_dest_port );
+
+ if( ( (status != CL_SUCCESS) || (*pp_dest_port == NULL) ) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ /*
+ This 'error' is the client's fault (bad lid) so
+ don't enter it as an error in our own log.
+ Return an error response to the client.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pr_rcv_get_end_points: "
+ "No dest port with LID = 0x%X.\n",
+ cl_ntoh16( p_pr->dlid) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( sa_status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_world(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const requestor_port,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ const cl_qmap_t* p_tbl;
+ const osm_port_t* p_dest_port;
+ const osm_port_t* p_src_port;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_world );
+
+ /*
+ Iterate the entire port space over itself.
+ A path record from a port to itself is legit, so no
+ need for a special case there.
+
+ We compute both A -> B and B -> A, since we don't have
+ any check to determine the reversability of the paths.
+ */
+ p_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+ p_dest_port = (osm_port_t*)cl_qmap_head( p_tbl );
+ while( p_dest_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+ {
+ p_src_port = (osm_port_t*)cl_qmap_head( p_tbl );
+ while( p_src_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+ {
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+ p_dest_port, comp_mask, p_list );
+
+ p_src_port = (osm_port_t*)cl_qmap_next( &p_src_port->map_item );
+ }
+
+ p_dest_port = (osm_port_t*)cl_qmap_next( &p_dest_port->map_item );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_half(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const requestor_port,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ const cl_qmap_t* p_tbl;
+ const osm_port_t* p_port;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_half );
+
+ /*
+ Iterate over every port, looking for matches...
+ A path record from a port to itself is legit, so no
+ need to special case that one.
+ */
+ p_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+ if( p_src_port )
+ {
+ /*
+ The src port if fixed, so iterate over destination ports.
+ */
+ p_port = (osm_port_t*)cl_qmap_head( p_tbl );
+ while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+ {
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+ p_port, comp_mask, p_list );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+ }
+ }
+ else
+ {
+ /*
+ The dest port if fixed, so iterate over source ports.
+ */
+ p_port = (osm_port_t*)cl_qmap_head( p_tbl );
+ while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+ {
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_port,
+ p_dest_port, comp_mask, p_list );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_pair(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_port_t* const requestor_port,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_pair );
+
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+ p_dest_port, comp_mask, p_list );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ *********************************************************************/
+static
+void
+__search_mgrp_by_mgid(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item;
+ osm_sa_pr_mcmr_search_ctxt_t *p_ctxt = (osm_sa_pr_mcmr_search_ctxt_t *) context;
+ const ib_gid_t *p_recvd_mgid;
+ osm_pr_rcv_t *p_rcv;
+ /* uint32_t i; */
+
+ p_recvd_mgid = p_ctxt->p_mgid;
+ p_rcv = p_ctxt->p_rcv;
+
+ /* Why not compare the entire MGID ???? */
+ /* different scope can sneak in for the same MGID ? */
+ /* EZ: I changed it to full compare ! */
+ if (cl_memcmp(&p_mgrp->mcmember_rec.mgid,
+ p_recvd_mgid,
+ sizeof(ib_gid_t)))
+ return;
+
+#if 0
+ for ( i = 0 ; i < sizeof(p_mgrp->mcmember_rec.mgid.multicast.raw_group_id); i++)
+ {
+ if (p_mgrp->mcmember_rec.mgid.multicast.raw_group_id[i] !=
+ p_recvd_mgid->mgid.multicast.raw_group_id[i])
+ return;
+ }
+#endif
+
+ if(p_ctxt->p_mgrp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__search_mgrp_by_mgid: ERR 1F08: "
+ "Multiple MCGROUP for same MGID.\n" );
+ return;
+ }
+ p_ctxt->p_mgrp = p_mgrp;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__get_mgrp_by_mgid(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN ib_path_rec_t* p_recvd_path_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ osm_sa_pr_mcmr_search_ctxt_t mcmr_search_context;
+
+ mcmr_search_context.p_mgid = &p_recvd_path_rec->dgid;
+ mcmr_search_context.p_rcv = p_rcv;
+ mcmr_search_context.p_mgrp = NULL;
+
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+ __search_mgrp_by_mgid,
+ &mcmr_search_context);
+
+ if(mcmr_search_context.p_mgrp == NULL)
+ {
+ return IB_NOT_FOUND;
+ }
+
+ *pp_mgrp = mcmr_search_context.p_mgrp;
+ return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+ IN const osm_pr_rcv_t* const p_rcv,
+ IN ib_net16_t const mlid)
+{
+ cl_map_item_t *map_item;
+
+ map_item = cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl,
+ mlid);
+ if(map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+ {
+ return NULL;
+ }
+
+ return (osm_mgrp_t *)map_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_get_mgrp(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ OUT osm_mgrp_t **pp_mgrp )
+{
+ ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_get_mgrp );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ if( comp_mask & IB_PR_COMPMASK_DGID )
+ {
+ status = __get_mgrp_by_mgid( p_rcv, p_pr, pp_mgrp );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_get_mgrp: ERR 1F09: "
+ "No MC group found for PathRecord destination GID.\n" );
+ goto Exit;
+ }
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_DLID )
+ {
+ if( *pp_mgrp)
+ {
+ /* check that the MLID in the MC group is */
+ /* the same as the DLID in the PathRecord */
+ if( (*pp_mgrp)->mlid != p_pr->dlid )
+ {
+ /* Note: perhaps this might be better indicated as an invalid request */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_get_mgrp: ERR 1F10: "
+ "MC group MLID does not match PathRecord destination LID.\n" );
+ *pp_mgrp = NULL;
+ goto Exit;
+ }
+ }
+ else
+ {
+ *pp_mgrp = __get_mgrp_by_mlid( p_rcv, p_pr->dlid );
+ if( *pp_mgrp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_get_mgrp: ERR 1F11: "
+ "No MC group found for PathRecord destination LID.\n" );
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_match_mgrp_attributes(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN const osm_mgrp_t* const p_mgrp )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ ib_api_status_t status = IB_ERROR;
+ uint32_t flow_label;
+ uint8_t sl;
+ uint8_t hop_limit;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_match_mgrp_attributes );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ /* If SGID and/or SLID specified, should validate as part of MC group */
+ /* Also, not checking MTU, rate, packet lifetime, and raw traffic currently */
+ if( comp_mask & IB_PR_COMPMASK_PKEY )
+ {
+ if( p_pr->pkey != p_mgrp->mcmember_rec.pkey )
+ goto Exit;
+ }
+
+ ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,
+ &sl, &flow_label, &hop_limit );
+
+ if( comp_mask & IB_PR_COMPMASK_SL )
+ {
+ if( ( p_pr->sl & 0xf ) != sl )
+ goto Exit;
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_NUMBPATH )
+ {
+ if( ( p_pr->num_path & 0x7f ) == 0 )
+ goto Exit;
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_FLOWLABEL )
+ {
+ if( ib_path_rec_flow_lbl( p_pr ) != flow_label )
+ goto Exit;
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_HOPLIMIT )
+ {
+ if( ib_path_rec_hop_limit( p_pr ) != hop_limit )
+ goto Exit;
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_TCLASS )
+ {
+ if( p_pr->tclass != p_mgrp->mcmember_rec.tclass )
+ goto Exit;
+ }
+
+ status = IB_SUCCESS;
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_pr_rcv_check_mcast_dest(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ boolean_t is_multicast = FALSE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_check_mcast_dest );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ if( comp_mask & IB_PR_COMPMASK_DGID )
+ {
+ is_multicast = ib_gid_is_multicast( &p_pr->dgid );
+ if( is_multicast )
+ goto Exit;
+ }
+
+ if( comp_mask & IB_PR_COMPMASK_DLID )
+ {
+ if( cl_ntoh16( p_pr->dlid ) >= IB_LID_MCAST_START_HO &&
+ cl_ntoh16( p_pr->dlid ) <= IB_LID_MCAST_END_HO )
+ is_multicast = TRUE;
+ else if( is_multicast )
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_check_mcast_dest: ERR 1F12: "
+ "PathRecord request indicates MGID but not MLID.\n" );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( is_multicast );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_respond(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ size_t num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+ size_t trim_num_rec;
+#endif
+ ib_path_rec_t* p_resp_pr;
+ ib_api_status_t status;
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ osm_pr_item_t* p_pr_item;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_respond );
+
+ num_rec = cl_qlist_count( p_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_respond: ERR 1F13: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+ /* need to set the mem free ... */
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ goto Exit;
+ }
+
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_path_rec_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pr_rcv_respond: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec,trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pr_rcv_respond: "
+ "Generating response with %u records.\n", num_rec );
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_path_rec_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_respond: ERR 1F14: "
+ "Unable to allocate MAD.\n" );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_path_rec_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ if ( num_rec == 0 )
+ {
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GET_RESP)
+ p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+ cl_memclr( p_resp_pr, sizeof(*p_resp_pr) );
+ }
+ else
+ {
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );
+
+ /* we need to track the number of copied items so we can
+ * stop the copy - but clear them all
+ */
+ num_copied = 0;
+
+ while( p_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )
+ {
+ /* Copy the Path Records from the list into the MAD */
+ if (num_copied < num_rec)
+ {
+ *p_resp_pr = p_pr_item->path_rec;
+ num_copied++;
+ }
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_resp_pr++;
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ }
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pr_rcv_respond: ERR 1F15: "
+ "Unable to send MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_process(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+ const osm_port_t* p_src_port;
+ const osm_port_t* p_dest_port;
+ cl_qlist_t pr_list;
+ ib_net16_t sa_status;
+ osm_port_t* requestor_port;
+ osm_mgrp_t* p_mgrp = NULL;
+ ib_api_status_t status;
+ osm_pr_item_t* p_pr_item;
+ uint32_t flow_label;
+ uint8_t sl;
+ uint8_t hop_limit;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ /* update the requestor physical port. */
+ requestor_port =
+ osm_get_port_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (requestor_port == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_process: ERR 1F16: "
+ "Cannot find requestor physical port.\n" );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD );
+
+ if ((p_sa_mad->method != IB_MAD_METHOD_GET) &&
+ (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_process: ERR 1F17: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_path_record( p_rcv->p_log, p_pr, OSM_LOG_DEBUG );
+
+ cl_qlist_init( &pr_list );
+
+ /*
+ Most SA functions (including this one) are read-only on the
+ subnet object, so we grab the lock non-exclusively.
+ */
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* Handle multicast destinations separately */
+ if( __osm_pr_rcv_check_mcast_dest( p_rcv, p_madw ) )
+ goto McastDest;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pr_rcv_process: "
+ "Unicast destination requested.\n" );
+
+ sa_status = __osm_pr_rcv_get_end_points( p_rcv, p_madw,
+ &p_src_port, &p_dest_port );
+
+ if( sa_status != IB_SA_MAD_STATUS_SUCCESS )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /*
+ What happens next depends on the type of endpoint information
+ that was specified....
+ */
+ if( p_src_port )
+ {
+ if( p_dest_port )
+ __osm_pr_rcv_process_pair( p_rcv, p_pr, requestor_port, p_src_port, p_dest_port,
+ p_sa_mad->comp_mask, &pr_list );
+ else
+ __osm_pr_rcv_process_half( p_rcv, p_pr, requestor_port, p_src_port, NULL,
+ p_sa_mad->comp_mask, &pr_list );
+ }
+ else
+ {
+ if( p_dest_port )
+ __osm_pr_rcv_process_half( p_rcv, p_pr, requestor_port, NULL, p_dest_port,
+ p_sa_mad->comp_mask, &pr_list );
+ else
+ /*
+ Katie, bar the door!
+ */
+ __osm_pr_rcv_process_world( p_rcv, p_pr, requestor_port,
+ p_sa_mad->comp_mask, &pr_list );
+ }
+ goto Unlock;
+
+ McastDest:
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pr_rcv_process: "
+ "Multicast destination requested.\n" );
+
+ /* First, get the MC info */
+ __osm_pr_get_mgrp( p_rcv, p_madw, &p_mgrp );
+
+ if ( p_mgrp )
+ {
+ /* Make sure the rest of the PathRecord matches the MC group attributes */
+ status = __osm_pr_match_mgrp_attributes( p_rcv, p_madw, p_mgrp);
+ if ( status == IB_SUCCESS )
+ {
+ p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );
+ if( p_pr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_process: ERR 1F18: "
+ "Unable to allocate path record for MC group.\n" );
+ }
+ else
+ {
+ /* Copy PathRecord request into response */
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+ p_pr_item->path_rec = *p_pr;
+
+ /* Now, use the MC info to cruft up the PathRecord response */
+ p_pr_item->path_rec.dgid = p_mgrp->mcmember_rec.mgid;
+ p_pr_item->path_rec.dlid = p_mgrp->mcmember_rec.mlid;
+ p_pr_item->path_rec.tclass = p_mgrp->mcmember_rec.tclass;
+ p_pr_item->path_rec.num_path = 1;
+ p_pr_item->path_rec.pkey = p_mgrp->mcmember_rec.pkey;
+
+ /* MTU, rate, and packet lifetime should be exactly */
+ p_pr_item->path_rec.mtu = (2<<6) | p_mgrp->mcmember_rec.mtu;
+ p_pr_item->path_rec.rate = (2<<6) | p_mgrp->mcmember_rec.rate;
+ p_pr_item->path_rec.pkt_life = (2<<6) | p_mgrp->mcmember_rec.pkt_life;
+
+ /* SL, Hop Limit, and Flow Label */
+ ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,
+ &sl, &flow_label, &hop_limit );
+ p_pr_item->path_rec.sl = sl;
+ p_pr_item->path_rec.hop_flow_raw = (uint32_t)(hop_limit) |
+ (flow_label << 8);
+
+ cl_qlist_insert_tail( &pr_list,
+ (cl_list_item_t*)&p_pr_item->pool_item );
+
+ }
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_process: ERR 1F19: "
+ "MC group attributes don't match PathRecord request.\n" );
+ }
+ }
+
+ /* Now, (finally) respond to the PathRecord request */
+
+ Unlock:
+ cl_plock_release( p_rcv->p_lock );
+ __osm_pr_rcv_respond( p_rcv, p_madw, &pr_list );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the PathRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pr_rcv_process( ((osm_pr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_construct(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_destroy(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pr_rcv_ctrl_init(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl,
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pr_rcv_ctrl_init );
+
+ osm_pr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PATH_RECORD,
+ __osm_pr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_ctrl_init: ERR 2001: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_pkey_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PKEY_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_PKEY_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_pkey_item
+{
+ cl_pool_item_t pool_item;
+ ib_pkey_table_record_t rec;
+
+} osm_pkey_item_t;
+
+typedef struct _osm_pkey_search_ctxt
+{
+ const ib_pkey_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ uint16_t block_num;
+ cl_qlist_t* p_list;
+ osm_pkey_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+
+} osm_pkey_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_construct(
+ IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_destroy(
+ IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_init );
+
+ osm_pkey_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_PKEY_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_PKEY_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_pkey_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_create(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN osm_pkey_search_ctxt_t* const p_ctxt,
+ IN uint16_t block)
+{
+ osm_pkey_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_create );
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ p_rec_item = (osm_pkey_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_pkey_create: ERR 4602: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_pkey_create: "
+ "New P_Key table for: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X Block:%u.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+ block
+ );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.block_num = block;
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.pkey_tbl =
+ *(osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp) , block));
+
+ cl_qlist_insert_tail( p_ctxt->p_list,
+ (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_check_physp(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ osm_pkey_search_ctxt_t* const p_ctxt )
+{
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ uint16_t block, num_blocks;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_check_physp );
+
+ /* we got here with the phys port - all is left is to get the right block */
+ if ( comp_mask & IB_PKEY_COMPMASK_BLOCK )
+ {
+ __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, p_ctxt->block_num);
+ }
+ else
+ {
+ num_blocks =
+ osm_pkey_tbl_get_num_blocks( osm_physp_get_pkey_tbl( p_physp ));
+ for (block = 0 ; block < num_blocks ; block++) {
+ __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, block );
+ }
+ }
+
+ //Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_by_comp_mask(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_pkey_search_ctxt_t* const p_ctxt )
+{
+ const ib_pkey_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ osm_physp_t * p_physp;
+ uint8_t port_num;
+ uint8_t num_ports;
+ const osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ port_num = p_rcvd_rec->port_num;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ /* if this is a switch port we can search all ports
+ otherwise we must be looking on port 0 */
+ if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ /* we put it in the comp mask and port num */
+ port_num = p_port->default_port_num;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_pkey_by_comp_mask: "
+ "Using Physical Default Port Number: 0x%X (for End Node).\n",
+ port_num);
+ comp_mask |= IB_PKEY_COMPMASK_PORT;
+ }
+
+ if( comp_mask & IB_PKEY_COMPMASK_PORT )
+ {
+ if (port_num < osm_port_get_num_physp( p_port ))
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ /* Check that the p_physp is valid, and that is shares a pkey
+ with the p_req_physp. */
+ if( p_physp && osm_physp_is_valid( p_physp ) &&
+ (osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) )
+ __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_pkey_by_comp_mask: ERR 4603: "
+ "Given Physical Port Number: 0x%X is out of range should be < 0x%X.\n",
+ port_num, osm_port_get_num_physp( p_port ));
+ goto Exit;
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requestor and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+ continue;
+
+ __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_pkey_search_ctxt_t* const p_ctxt = (osm_pkey_search_ctxt_t *)context;
+
+ __osm_sa_pkey_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_process(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_pkey_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_pkey_table_t* p_pkey;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_pkey_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_pkey_search_ctxt_t context;
+ osm_pkey_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_pkey_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+ comp_mask = p_rcvd_mad->comp_mask;
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PKEY_TBL_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4604: "
+ "Cannot find requestor physical port.\n" );
+ goto Exit;
+ }
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4605: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ /*
+ p819 - P_KeyTableRecords shall only be provided in response
+ to trusted requests.
+ Check that the requestor is a trusted one.
+ */
+ if ( p_rcvd_mad->sm_key != p_rcv->p_subn->opt.sm_key )
+ {
+ /* This is not a trusted requestor! */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process ERR 4608: "
+ "Request from non-trusted requestor: "
+ "Given SM_Key:0x%016" PRIx64 "\n",
+ cl_ntoh64(p_rcvd_mad->sm_key) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ p_pkey = (ib_pkey_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ cl_qlist_init( &rec_list );
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.block_num = p_rcvd_rec->block_num;
+ context.p_req_physp = p_req_physp;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pkey_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%02X), Block:0x%02X(%02X), Port:0x%02X(%02X).\n",
+ cl_ntoh16(p_rcvd_rec->lid), (comp_mask &IB_PKEY_COMPMASK_LID) != 0,
+ p_rcvd_rec->port_num, (comp_mask &IB_PKEY_COMPMASK_PORT) != 0,
+ p_rcvd_rec->block_num, (comp_mask &IB_PKEY_COMPMASK_BLOCK) != 0) ;
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /*
+ If the user specified a LID, it obviously narrows our
+ work load, since we don't have to search every port
+ */
+ if( comp_mask & IB_PKEY_COMPMASK_LID )
+ {
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ else
+ { /* port out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: "
+ "Given LID (%u) is out of range:%u.\n",
+ cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+
+ /* if we got a unique port - no need for a port search */
+ if( p_port )
+ /* this does the loop on all the port phys ports */
+ __osm_sa_pkey_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_pkey_by_comp_mask_cb,
+ &context );
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_pkey_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_pkey_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_rec_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pkey_rec_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_pkey_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4606: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_pkey_table_record_t) );
+
+ p_resp_rec = (ib_pkey_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4607: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pkey_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pkey_rec_rcv_process( ((osm_pkey_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_construct(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_destroy(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_ctrl_init(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_ctrl_init );
+
+ osm_pkey_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PKEY_TBL_RECORD,
+ __osm_pkey_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_ctrl_init: ERR 4701: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pir_rcv_t.
+ * This object represents the PortInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_portinfo_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PIR_RCV_POOL_MIN_SIZE 32
+#define OSM_PIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_pir_item
+{
+ cl_pool_item_t pool_item;
+ ib_portinfo_record_t rec;
+
+} osm_pir_item_t;
+
+typedef struct _osm_pir_search_ctxt
+{
+ const ib_portinfo_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ cl_qlist_t* p_list;
+ osm_pir_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+
+} osm_pir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_construct(
+ IN osm_pir_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_destroy(
+ IN osm_pir_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_init(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_pir_rcv_init );
+
+ osm_pir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_PIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_PIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_pir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pir_rcv_new_pir(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid )
+{
+ osm_pir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pir_rcv_new_pir );
+
+ p_rec_item = (osm_pir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pir_rcv_new_pir: ERR 2102: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pir_rcv_new_pir: "
+ "New PortInfoRecord: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ) );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.port_info = *osm_physp_get_port_info_ptr( p_physp );
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_create(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN osm_pir_search_ctxt_t* const p_ctxt )
+{
+ uint8_t lmc;
+ uint16_t lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t base_lid_ho;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_create );
+
+ if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+ {
+ lmc = 0;
+ base_lid_ho = cl_ntoh16(
+ osm_physp_get_base_lid(
+ osm_node_get_physp_ptr(p_physp->p_node, 0))
+ );
+ max_lid_ho = base_lid_ho;
+ }
+ else
+ {
+ lmc = osm_physp_get_lmc( p_physp );
+ base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) );
+ max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+ }
+
+ if( p_ctxt->comp_mask & IB_PIR_COMPMASK_LID )
+ {
+ __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+ p_ctxt->p_rcvd_rec->lid );
+ }
+ else
+ {
+ for( lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+ cl_hton16( lid_ho ) );
+ }
+ }
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_check_physp(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ osm_pir_search_ctxt_t* const p_ctxt )
+{
+ const ib_portinfo_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ const ib_port_info_t* p_comp_pi;
+ const ib_port_info_t* p_pi;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_check_physp );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ p_comp_pi = &p_rcvd_rec->port_info;
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ osm_dump_port_info(
+ p_rcv->p_log,
+ osm_node_get_node_guid( p_physp->p_node ),
+ p_physp->port_guid,
+ p_physp->port_num,
+ &p_physp->port_info,
+ OSM_LOG_DEBUG );
+
+ if( comp_mask & IB_PIR_COMPMASK_MKEY )
+ {
+ if( p_comp_pi->m_key != p_pi->m_key )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_GIDPRE )
+ {
+ if( p_comp_pi->subnet_prefix != p_pi->subnet_prefix )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_SMLID )
+ {
+ if( p_comp_pi->master_sm_base_lid != p_pi->master_sm_base_lid )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_CAPMASK )
+ {
+ if( p_comp_pi->capability_mask != p_pi->capability_mask )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_DIAGCODE )
+ {
+ if( p_comp_pi->diag_code != p_pi->diag_code )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_MKEYLEASEPRD )
+ {
+ if( p_comp_pi->m_key_lease_period != p_pi->m_key_lease_period )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LOCALPORTNUM )
+ {
+ if( p_comp_pi->local_port_num != p_pi->local_port_num )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHSUPPORT )
+ {
+ if( p_comp_pi->link_width_supported != p_pi->link_width_supported )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHACTIVE )
+ {
+ if( p_comp_pi->link_width_active != p_pi->link_width_active )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LINKWIDTHENABLED )
+ {
+ if( p_comp_pi->link_width_enabled != p_pi->link_width_enabled )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LNKSPEEDSUPPORT )
+ {
+ if( ib_port_info_get_link_speed_sup( p_comp_pi )!=
+ ib_port_info_get_link_speed_sup( p_pi) )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_PORTSTATE )
+ {
+ if( ib_port_info_get_port_state( p_comp_pi ) !=
+ ib_port_info_get_port_state( p_pi ) )
+ goto Exit;
+ }
+ if ( comp_mask & IB_PIR_COMPMASK_PORTPHYSTATE )
+ {
+ if ( ib_port_info_get_port_phys_state( p_comp_pi ) !=
+ ib_port_info_get_port_phys_state( p_pi ) )
+ goto Exit;
+ }
+ if ( comp_mask & IB_PIR_COMPMASK_LINKDWNDFLTSTATE )
+ {
+ if ( ib_port_info_get_link_down_def_state( p_comp_pi ) !=
+ ib_port_info_get_link_down_def_state( p_pi ) )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_LMC )
+ {
+ if( ib_port_info_get_lmc( p_comp_pi ) !=
+ ib_port_info_get_lmc( p_pi ) )
+ goto Exit;
+ }
+ if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDACTIVE )
+ {
+ if ( ib_port_info_get_link_speed_active( p_comp_pi ) !=
+ ib_port_info_get_link_speed_active( p_pi ) )
+ goto Exit;
+ }
+ if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDENABLE )
+ {
+ if ( ib_port_info_get_link_speed_enabled( p_comp_pi ) !=
+ ib_port_info_get_link_speed_enabled( p_pi ) )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_NEIGHBORMTU )
+ {
+ if( ib_port_info_get_neighbor_mtu( p_comp_pi ) !=
+ ib_port_info_get_neighbor_mtu( p_pi ) )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_VLHIGHLIMIT )
+ {
+ if( p_comp_pi->vl_high_limit != p_pi->vl_high_limit )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_VLARBHIGHCAP )
+ {
+ if( p_comp_pi->vl_arb_high_cap != p_pi->vl_arb_high_cap )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_VLARBLOWCAP )
+ {
+ if( p_comp_pi->vl_arb_low_cap != p_pi->vl_arb_low_cap )
+ goto Exit;
+ }
+ if( comp_mask & IB_PIR_COMPMASK_MTUCAP )
+ {
+ if( ib_port_info_get_mtu_cap( p_comp_pi ) !=
+ ib_port_info_get_mtu_cap( p_pi ) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_HOQLIFE )
+ {
+ if ((p_comp_pi->vl_stall_life & 0x1F) != (p_pi->vl_stall_life & 0x1F) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_OPVLS )
+ {
+ if ((p_comp_pi->vl_enforce & 0xF0) != (p_pi->vl_enforce & 0xF0) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_PARENFIN )
+ {
+ if ((p_comp_pi->vl_enforce & 0x08) != (p_pi->vl_enforce & 0x08) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_PARENFOUT )
+ {
+ if ((p_comp_pi->vl_enforce & 0x04) != (p_pi->vl_enforce & 0x04) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_FILTERRAWIN )
+ {
+ if ((p_comp_pi->vl_enforce & 0x02) != (p_pi->vl_enforce & 0x02) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_FILTERRAWOUT )
+ {
+ if ((p_comp_pi->vl_enforce & 0x01) != (p_pi->vl_enforce & 0x01) )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_MKEYVIO )
+ {
+ if (p_comp_pi->m_key_violations != p_pi->m_key_violations )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_PKEYVIO )
+ {
+ if (p_comp_pi->p_key_violations != p_pi->p_key_violations )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_QKEYVIO )
+ {
+ if (p_comp_pi->q_key_violations != p_pi->q_key_violations )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_GUIDCAP )
+ {
+ if (p_comp_pi->guid_cap != p_pi->guid_cap )
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_SUBNTO )
+ {
+ if (ib_port_info_get_timeout(p_comp_pi) != ib_port_info_get_timeout(p_pi))
+ goto Exit;
+ }
+ if (comp_mask & IB_PIR_COMPMASK_RESPTIME )
+ {
+ if ((p_comp_pi->resp_time_value & 0x1F) != (p_pi->resp_time_value &0x1F) )
+ goto Exit;
+ }
+
+ __osm_sa_pir_create( p_rcv, p_physp, p_ctxt );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_by_comp_mask(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_pir_search_ctxt_t* const p_ctxt )
+{
+ const ib_portinfo_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ const osm_physp_t* p_physp;
+ uint8_t port_num;
+ uint8_t num_ports;
+ const osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ num_ports = osm_port_get_num_physp( p_port );
+
+ if( comp_mask & IB_PIR_COMPMASK_PORTNUM )
+ {
+ if (p_rcvd_rec->port_num < num_ports)
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, p_rcvd_rec->port_num );
+ /* Check that the p_physp is valid, and that the p_physp and the
+ p_req_physp share a pkey. */
+ if( p_physp && osm_physp_is_valid( p_physp ) &&
+ osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+ __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ else
+ {
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requestor and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+ continue;
+
+ __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_pir_search_ctxt_t* const p_ctxt = (osm_pir_search_ctxt_t *)context;
+
+ __osm_sa_pir_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_process(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_portinfo_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_port_info_t* p_pi;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_portinfo_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_pir_search_ctxt_t context;
+ osm_pir_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+ boolean_t trusted_req = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_portinfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+ comp_mask = p_rcvd_mad->comp_mask;
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2104: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2105: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ p_pi = &p_rcvd_rec->port_info;
+
+ cl_qlist_init( &rec_list );
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ /*
+ If the user specified a LID, it obviously narrows our
+ work load, since we don't have to search every port
+ */
+ if( comp_mask & IB_PIR_COMPMASK_LID )
+ {
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: "
+ "Given LID (%u) is out of range:%u.\n",
+ cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+ else
+ {
+ if( comp_mask & IB_PIR_COMPMASK_BASELID )
+ {
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_pi->base_lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_pi->base_lid) );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: "
+ "Given LID (%u) is out of range:%u.\n",
+ cl_ntoh16(p_pi->base_lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+ }
+
+ if( p_port )
+ __osm_sa_pir_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_pir_by_comp_mask_cb,
+ &context );
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_pir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_portinfo_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pir_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pir_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_portinfo_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2106: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_portinfo_record_t) );
+
+ p_resp_rec = (ib_portinfo_record_t*)
+ ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ /*
+ p819 - The M_Key returned shall be zero, except in the case of a
+ trusted request.
+ Note: In the mad controller we check that the SM_Key received on
+ the mad is valid. Meaning - is either zero or equal to the local
+ sm_key.
+ */
+ if (p_rcvd_mad->sm_key == 0)
+ trusted_req = FALSE;
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ if (trusted_req == FALSE)
+ p_resp_rec->port_info.m_key = 0;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2107: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pir_rcv_ctrl_t.
+ * This object represents the PortInfoRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pir_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pir_rcv_process( ((osm_pir_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_construct(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_destroy(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_ctrl_init(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl,
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pir_rcv_ctrl_init );
+
+ osm_pir_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PORTINFO_RECORD,
+ __osm_pir_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_ctrl_init: ERR 2201: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_resp_t.
+ * This object represents the generic attribute respuester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+ Next available error code: 0x300
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_construct(
+ IN osm_sa_resp_t* const p_resp )
+{
+ cl_memclr( p_resp, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_destroy(
+ IN osm_sa_resp_t* const p_resp )
+{
+ CL_ASSERT( p_resp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_resp_init(
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_resp_init );
+
+ osm_sa_resp_construct( p_resp );
+
+ p_resp->p_log = p_log;
+ p_resp->p_pool = p_pool;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_send_error(
+ IN osm_sa_resp_t* const p_resp,
+ IN const osm_madw_t* const p_madw,
+ IN const ib_net16_t sa_status )
+{
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_sa_mad_t* p_sa_mad;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_resp->p_log, osm_sa_send_error );
+
+ /* avoid races - if we are exiting - exit */
+ if (osm_exit_flag)
+ {
+ osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+ "osm_sa_send_error: ",
+ "Ignoring requested send after exit.\n" );
+ goto Exit;
+ }
+
+ p_resp_madw = osm_mad_pool_get( p_resp->p_pool,
+ p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr );
+
+ if( p_resp_madw == NULL )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_sa_send_error: ERR 2301: "
+ "Unable to acquire response MAD.\n" );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /* Copy the MAD header back into the response mad */
+ *p_resp_sa_mad = *p_sa_mad;
+ p_resp_sa_mad->status = sa_status;
+
+ if( p_resp_sa_mad->method == IB_MAD_METHOD_SET )
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+
+ /*
+ * C15-0.1.5 - always return SM_Key = 0 (table 151 p 782)
+ */
+ p_resp_sa_mad->sm_key = 0;
+
+ if( osm_log_is_active( p_resp->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_resp->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+ status = osm_vendor_send( osm_madw_get_bind_handle( p_resp_madw ),
+ p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_sa_send_error: ERR 2302: "
+ "Error sending MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_resp->p_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_resp->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_service_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_service.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SR_RCV_POOL_MIN_SIZE 64
+#define OSM_SR_RCV_POOL_GROW_SIZE 64
+
+typedef struct _osm_sr_item
+{
+ cl_pool_item_t pool_item;
+ ib_service_record_t service_rec;
+
+} osm_sr_item_t;
+
+
+typedef struct osm_sr_match_item {
+ cl_qlist_t sr_list;
+ ib_service_record_t* p_service_rec;
+ ib_net64_t comp_mask;
+ osm_sr_rcv_t* p_rcv;
+
+}osm_sr_match_item_t;
+
+typedef struct _osm_sr_search_ctxt
+{
+ osm_sr_match_item_t * p_sr_item;
+ const osm_physp_t* p_req_physp;
+} osm_sr_search_ctxt_t;
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_construct(
+ IN osm_sr_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->sr_pool );
+ cl_timer_construct(&p_rcv->sr_timer );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_destroy(
+ IN osm_sr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->sr_pool );
+ cl_timer_trim(&p_rcv->sr_timer, 1);
+ cl_timer_destroy(&p_rcv->sr_timer );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_init(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_ERROR;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_log, osm_sr_rcv_init );
+
+ osm_sr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ cl_status = cl_qlock_pool_init( &p_rcv->sr_pool,
+ OSM_SR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_sr_item_t),
+ NULL, NULL, NULL );
+ if(cl_status != CL_SUCCESS)
+ goto Exit;
+
+ status = cl_timer_init(&p_rcv->sr_timer,
+ osm_sr_rcv_lease_cb,
+ p_rcv );
+ if(cl_status != CL_SUCCESS)
+ goto Exit;
+
+ status = IB_SUCCESS;
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+boolean_t
+__match_service_pkey_with_ports_pkey(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ ib_service_record_t * const p_service_rec,
+ ib_net64_t const comp_mask)
+{
+ boolean_t valid = TRUE;
+ osm_physp_t *p_req_physp;
+ ib_net64_t service_guid;
+ osm_port_t *service_port;
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__match_service_pkey_with_ports_pkey: ERR 2404: "
+ "Cannot find requestor physical port. \n" );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY)
+ {
+ /* We have a ServiceP_Key - check matching on requestor port, and
+ ServiceGid port (if such exists) */
+ /* Make sure it matches the p_req_physp */
+ if (!osm_physp_has_pkey(p_rcv->p_log, p_service_rec->service_pkey, p_req_physp ))
+ {
+ valid = FALSE;
+ goto Exit;
+ }
+ /* Make sure it matches the port of the ServiceGid */
+ if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID)
+ {
+ service_guid = p_service_rec->service_gid.unicast.interface_id;
+ service_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, service_guid );
+ if (service_port == (osm_port_t*)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__match_service_pkey_with_ports_pkey: ERR 2405: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( service_guid ) );
+ valid = FALSE;
+ goto Exit;
+ }
+ /* check on the table of the default physical port of the service port */
+ if ( !osm_physp_has_pkey( p_rcv->p_log,
+ p_service_rec->service_pkey,
+ osm_port_get_default_phys_ptr(service_port) ))
+ {
+ valid = FALSE;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ return valid;
+}
+/**********************************************************************
+ **********************************************************************/
+
+boolean_t
+__match_name_to_key_association(
+ IN osm_sr_rcv_t* const p_rcv,
+ ib_service_record_t* p_service_rec,
+ ib_net64_t comp_mask)
+{
+ UNUSED_PARAM( p_service_rec );
+ UNUSED_PARAM( p_rcv );
+ if( (comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) ==
+ (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME) )
+ {
+ /* For now we are not maintaining the ServiceAssociation record
+ * just return TRUE
+ */
+
+ return TRUE;
+
+ }
+
+ return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static
+boolean_t
+__validate_sr(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ boolean_t valid = TRUE;
+ ib_sa_mad_t *p_sa_mad;
+ ib_service_record_t* p_recvd_service_rec;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_sr );
+
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_service_rec =
+ (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ valid = __match_service_pkey_with_ports_pkey(
+ p_rcv,
+ p_madw,
+ p_recvd_service_rec,
+ p_sa_mad->comp_mask);
+
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_sr: "
+ "No Match for Service Pkey\n");
+ valid = FALSE;
+ goto Exit;
+ }
+
+ valid = __match_name_to_key_association(
+ p_rcv,
+ p_recvd_service_rec,
+ p_sa_mad->comp_mask);
+
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_sr: "
+ "Service Record Name to key matching failed\n");
+ valid = FALSE;
+ goto Exit;
+ }
+
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return valid;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_respond(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ ib_service_record_t* p_resp_sr;
+ ib_api_status_t status;
+ osm_sr_item_t* p_sr_item;
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ boolean_t trusted_req = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sr_rcv_respond );
+
+ num_rec = cl_qlist_count( p_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2406: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_service_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sr_rcv_respond: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sr_rcv_respond: "
+ "Generating response with %u records.\n", num_rec );
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_service_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2402: "
+ "Unable to allocate MAD.\n" );
+ /* Release the quick pool items */
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+
+ /* but what if it was a SET ? setting the response bit is not enough */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_SET)
+ {
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+ }
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_service_record_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_sr = (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ if( (p_resp_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) &&
+ (num_rec == 0))
+ {
+ p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+ cl_memclr( p_resp_sr, sizeof(*p_resp_sr) );
+ }
+ else
+ {
+ /*
+ p819 - The ServiceKey shall be set to 0, except in the case of a trusted
+ request.
+ Note: In the mad controller we check that the SM_Key received on
+ the mad is valid. Meaning - is either zero or equal to the local
+ sm_key.
+ */
+ if (p_sa_mad->sm_key == 0)
+ trusted_req = FALSE;
+
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+
+ /* we need to track the number of copied items so we can
+ * stop the copy - but clear them all
+ */
+ num_copied = 0;
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ /* Copy the Link Records from the list into the MAD */
+ if (num_copied < num_rec)
+ {
+ *p_resp_sr = p_sr_item->service_rec;
+ if (trusted_req == FALSE)
+ cl_memclr(p_resp_sr->service_key, sizeof(p_resp_sr->service_key));
+
+ num_copied++;
+ }
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_resp_sr++;
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ }
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2407: "
+ "Unable to send MAD (%s).\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+/**********************************************************************
+ **********************************************************************/
+
+static
+void
+__get_matching_sr(
+ IN cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ osm_sr_search_ctxt_t* const p_ctxt = (osm_sr_search_ctxt_t*)context;
+ osm_svcr_t *p_svcr = (osm_svcr_t*)p_list_item;
+ osm_sr_item_t* p_sr_pool_item;
+ osm_sr_match_item_t* p_sr_item =p_ctxt->p_sr_item;
+ ib_net64_t comp_mask = p_sr_item->comp_mask;
+ const osm_physp_t* p_req_physp = p_ctxt->p_req_physp;
+
+
+ if((comp_mask & IB_SR_COMPMASK_SID) == IB_SR_COMPMASK_SID)
+ {
+ if(p_sr_item->p_service_rec->service_id !=
+ p_svcr->service_record.service_id)
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID)
+ {
+ if(
+ cl_memcmp(&p_sr_item->p_service_rec->service_gid,
+ &p_svcr->service_record.service_gid,
+ sizeof(p_svcr->service_record.service_gid)) != 0)
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY )
+ {
+ if(p_sr_item->p_service_rec->service_pkey !=
+ p_svcr->service_record.service_pkey)
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SKEY) == IB_SR_COMPMASK_SKEY)
+ {
+ if(cl_memcmp(p_sr_item->p_service_rec->service_key ,
+ p_svcr->service_record.service_key,
+ 16*sizeof(uint8_t)))
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SNAME) == IB_SR_COMPMASK_SNAME)
+ {
+ if(
+ cl_memcmp(p_sr_item->p_service_rec->service_name,
+ p_svcr->service_record.service_name,
+ sizeof(p_svcr->service_record.service_name)) != 0
+ )
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_0) == IB_SR_COMPMASK_SDATA8_0)
+ {
+ if(p_sr_item->p_service_rec->service_data8[0] !=
+ p_svcr->service_record.service_data8[0])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_1) == IB_SR_COMPMASK_SDATA8_1)
+ {
+ if(p_sr_item->p_service_rec->service_data8[1] !=
+ p_svcr->service_record.service_data8[1])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_2) == IB_SR_COMPMASK_SDATA8_2)
+ {
+ if(p_sr_item->p_service_rec->service_data8[2] !=
+ p_svcr->service_record.service_data8[2])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_3) == IB_SR_COMPMASK_SDATA8_3)
+ {
+ if(p_sr_item->p_service_rec->service_data8[3] !=
+ p_svcr->service_record.service_data8[3])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_4)== IB_SR_COMPMASK_SDATA8_4)
+ {
+ if(p_sr_item->p_service_rec->service_data8[4] !=
+ p_svcr->service_record.service_data8[4])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_5)== IB_SR_COMPMASK_SDATA8_5)
+ {
+ if(p_sr_item->p_service_rec->service_data8[5] !=
+ p_svcr->service_record.service_data8[5])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_6)== IB_SR_COMPMASK_SDATA8_6)
+ {
+ if(p_sr_item->p_service_rec->service_data8[6]!=
+ p_svcr->service_record.service_data8[6])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_7)== IB_SR_COMPMASK_SDATA8_7)
+ {
+ if(p_sr_item->p_service_rec->service_data8[7]!=
+ p_svcr->service_record.service_data8[7])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_8)== IB_SR_COMPMASK_SDATA8_8)
+ {
+ if(p_sr_item->p_service_rec->service_data8[8]!=
+ p_svcr->service_record.service_data8[8])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_9)== IB_SR_COMPMASK_SDATA8_9)
+ {
+ if(p_sr_item->p_service_rec->service_data8[9]!=
+ p_svcr->service_record.service_data8[9])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_10)== IB_SR_COMPMASK_SDATA8_10)
+ {
+ if(p_sr_item->p_service_rec->service_data8[10]!=
+ p_svcr->service_record.service_data8[10])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_11)== IB_SR_COMPMASK_SDATA8_11)
+ {
+ if(p_sr_item->p_service_rec->service_data8[11]!=
+ p_svcr->service_record.service_data8[11])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_12)== IB_SR_COMPMASK_SDATA8_12)
+ {
+ if(p_sr_item->p_service_rec->service_data8[12]!=
+ p_svcr->service_record.service_data8[12])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_13)== IB_SR_COMPMASK_SDATA8_13)
+ {
+ if(p_sr_item->p_service_rec->service_data8[13]!=
+ p_svcr->service_record.service_data8[13])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_14)== IB_SR_COMPMASK_SDATA8_14)
+ {
+ if(p_sr_item->p_service_rec->service_data8[14]!=
+ p_svcr->service_record.service_data8[14])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA8_15)== IB_SR_COMPMASK_SDATA8_15)
+ {
+ if(p_sr_item->p_service_rec->service_data8[15]!=
+ p_svcr->service_record.service_data8[15])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_0)== IB_SR_COMPMASK_SDATA16_0)
+ {
+ if(p_sr_item->p_service_rec->service_data16[0]!=
+ p_svcr->service_record.service_data16[0])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_1)== IB_SR_COMPMASK_SDATA16_1)
+ {
+ if(p_sr_item->p_service_rec->service_data16[1]!=
+ p_svcr->service_record.service_data16[1])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_2)== IB_SR_COMPMASK_SDATA16_2)
+ {
+ if(p_sr_item->p_service_rec->service_data16[2]!=
+ p_svcr->service_record.service_data16[2])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_3)== IB_SR_COMPMASK_SDATA16_3)
+ {
+ if(p_sr_item->p_service_rec->service_data16[3]!=
+ p_svcr->service_record.service_data16[3])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_4)== IB_SR_COMPMASK_SDATA16_4)
+ {
+ if(p_sr_item->p_service_rec->service_data16[4]!=
+ p_svcr->service_record.service_data16[4])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_5)== IB_SR_COMPMASK_SDATA16_5)
+ {
+ if(p_sr_item->p_service_rec->service_data16[5]!=
+ p_svcr->service_record.service_data16[5])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_6)== IB_SR_COMPMASK_SDATA16_6)
+ {
+ if(p_sr_item->p_service_rec->service_data16[6]!=
+ p_svcr->service_record.service_data16[6])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA16_7)== IB_SR_COMPMASK_SDATA16_7)
+ {
+ if(p_sr_item->p_service_rec->service_data16[7]!=
+ p_svcr->service_record.service_data16[7])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA32_0)== IB_SR_COMPMASK_SDATA32_0)
+ {
+ if(p_sr_item->p_service_rec->service_data32[0]!=
+ p_svcr->service_record.service_data32[0])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA32_1)== IB_SR_COMPMASK_SDATA32_1)
+ {
+ if(p_sr_item->p_service_rec->service_data32[1]!=
+ p_svcr->service_record.service_data32[1])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA32_2)== IB_SR_COMPMASK_SDATA32_2)
+ {
+ if(p_sr_item->p_service_rec->service_data32[2]!=
+ p_svcr->service_record.service_data32[2])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA32_3)== IB_SR_COMPMASK_SDATA32_3)
+ {
+ if(p_sr_item->p_service_rec->service_data32[3]!=
+ p_svcr->service_record.service_data32[3])
+ return;
+ }
+
+ if((comp_mask & IB_SR_COMPMASK_SDATA64_0)== IB_SR_COMPMASK_SDATA64_0)
+ {
+ if(p_sr_item->p_service_rec->service_data64[0]!=
+ p_svcr->service_record.service_data64[0])
+ return;
+ }
+ if((comp_mask & IB_SR_COMPMASK_SDATA64_1)== IB_SR_COMPMASK_SDATA64_1)
+ {
+ if(p_sr_item->p_service_rec->service_data64[1]!=
+ p_svcr->service_record.service_data64[1])
+ return;
+ }
+
+ /* Check that the requestor port has the pkey which is the service_pkey.
+ If not - then it cannot receive this serviceRecord. */
+ /* The check is relevant only if the service_pkey is valid */
+ if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey))
+ {
+ if (!osm_physp_has_pkey( p_sr_item->p_rcv->p_log,
+ p_svcr->service_record.service_pkey,
+ p_req_physp ) )
+ {
+ osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_matching_sr: "
+ "requestor port doesn't have the service_pkey: 0x%X\n",
+ cl_ntoh16(p_svcr->service_record.service_pkey) );
+ return;
+ }
+ }
+
+ p_sr_pool_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_sr_item->p_rcv->sr_pool );
+
+ if( p_sr_pool_item == NULL )
+ {
+ osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_matching_sr: ERR 2408: "
+ "Unable to acquire Service Record form Pool.\n");
+ goto Exit;
+ }
+
+ p_sr_pool_item->service_rec = p_svcr->service_record;
+
+ cl_qlist_insert_tail( &p_sr_item->sr_list,
+ (cl_list_item_t*)&p_sr_pool_item->pool_item );
+
+ Exit:
+ return;
+}
+/**********************************************************************
+ **********************************************************************/
+
+static
+void
+osm_sr_rcv_process_get_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_service_record_t* p_recvd_service_rec;
+ osm_sr_match_item_t sr_match_item;
+ osm_sr_search_ctxt_t context;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_get_method );
+
+ CL_ASSERT( p_madw );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_get_method: ERR 2409: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_service_rec =
+ (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ cl_qlist_init(&sr_match_item.sr_list);
+ sr_match_item.p_service_rec = p_recvd_service_rec;
+ sr_match_item.comp_mask = p_sa_mad->comp_mask;
+ sr_match_item.p_rcv = p_rcv;
+
+ context.p_sr_item = &sr_match_item;
+ context.p_req_physp = p_req_physp;
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ cl_qlist_apply_func(&p_rcv->p_subn->sa_sr_list,
+ __get_matching_sr,
+ &context);
+
+ if ((p_sa_mad->method == IB_MAD_METHOD_GET) &&
+ (cl_qlist_count( &sr_match_item.sr_list ) == 0))
+ {
+ cl_plock_release(p_rcv->p_lock);
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_get_method: "
+ "No Records Matched the query Service Record\n");
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ cl_plock_release(p_rcv->p_lock);
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_match_item.sr_list );
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+
+}
+/**********************************************************************
+ **********************************************************************/
+static
+void
+osm_sr_rcv_process_set_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ ib_service_record_t* p_recvd_service_rec;
+ ib_net64_t comp_mask;
+ osm_svcr_t* p_svcr;
+ osm_sr_item_t* p_sr_item;
+ cl_qlist_t sr_list;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_set_method );
+
+ CL_ASSERT( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_service_rec =
+ (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_service_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ OSM_LOG_DEBUG );
+ }
+
+ if( (comp_mask & ( IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID )) !=
+ (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_sr_rcv_process_set_method: "
+ "Component Mask RID check failed for METHOD_SET\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+
+ /* if we were not provided with a service lease make it
+ infinite */
+ if( (comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_set_method: "
+ "ServiceLease Component Mask not set - using infinite lease\n");
+ p_recvd_service_rec->service_lease = 0xFFFFFFFF;
+ }
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ /* If Record exists with matching RID */
+ p_svcr = osm_svcr_get_by_rid(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_recvd_service_rec);
+
+ if(p_svcr == NULL)
+ {
+ /* Create the instance of the osm_svcr_t object */
+ p_svcr = osm_svcr_new(p_recvd_service_rec);
+ if(p_svcr == NULL)
+ {
+ cl_plock_release(p_rcv->p_lock);
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_set_method: ERR 2411: "
+ "osm_svcr_get_by_rid failed\n");
+
+ osm_sa_send_error(
+ p_rcv->p_resp,
+ p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES);
+
+ goto Exit;
+
+ }
+ /* Add this new osm_svcr_t object to subnet object */
+ osm_svcr_insert_to_db(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_svcr);
+
+ } else
+ {
+
+ /* Update the old instance of the osm_svcr_t object */
+ osm_svcr_init(p_svcr, p_recvd_service_rec);
+
+ }
+ cl_plock_release(p_rcv->p_lock);
+
+ if( p_recvd_service_rec->service_lease != 0xFFFFFFFF )
+ {
+ /* cl_timer_trim(&p_rcv->sr_timer, */
+ /* p_recvd_service_rec->service_lease * 1000 ); */
+ /* This was a bug since no check was made to see if too long */
+ /* just make sure the timer works - geta call back within a second */
+ cl_timer_trim(&p_rcv->sr_timer, 1000);
+ p_svcr->modified_time = cl_get_time_stamp_sec();
+ }
+
+ p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+ if( p_sr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_set_method: ERR 2412: "
+ "Unable to acquire Service record.\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ if( (comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY)
+ {
+ /* Set the Default Service P_Key in the response */
+ p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY;
+ }
+
+ p_sr_item->service_rec = *p_recvd_service_rec;
+ cl_qlist_init(&sr_list);
+
+ cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+/**********************************************************************
+ **********************************************************************/
+
+static
+void
+osm_sr_rcv_process_delete_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_service_record_t* p_recvd_service_rec;
+ ib_net64_t comp_mask;
+ osm_svcr_t* p_svcr;
+ osm_sr_item_t* p_sr_item;
+ cl_qlist_t sr_list;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_delete_method );
+
+ CL_ASSERT( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_service_rec =
+ (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ comp_mask = p_sa_mad->comp_mask;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_service_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ OSM_LOG_DEBUG );
+ }
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ /* If Record exists with matching RID */
+ p_svcr = osm_svcr_get_by_rid(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_recvd_service_rec);
+
+ if(p_svcr == NULL)
+ {
+ cl_plock_release(p_rcv->p_lock);
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_delete_method: "
+ "No Records Matched the RID\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ else
+ {
+ osm_svcr_remove_from_db(p_rcv->p_subn,
+ p_rcv->p_log,
+ p_svcr);
+ }
+
+ cl_plock_release(p_rcv->p_lock);
+
+ p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+ if( p_sr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_delete_method: ERR 2413: "
+ "Unable to acquire Service record.\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ /* provide back the copy of the record */
+ p_sr_item->service_rec = p_svcr->service_record;
+ cl_qlist_init(&sr_list);
+
+ cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+ if(p_svcr) osm_svcr_destroy(p_svcr);
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_sr_rcv_process(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ ib_service_record_t* p_recvd_service_rec;
+ boolean_t valid;
+
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process );
+
+ CL_ASSERT( p_madw );
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_recvd_service_rec =
+ (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ switch (p_sa_mad->method)
+ {
+ case IB_MAD_METHOD_SET:
+ valid = __validate_sr(p_rcv, p_madw);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_sr_rcv_process: "
+ "Component Mask check failed\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+ osm_sr_rcv_process_set_method(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_DELETE:
+ valid = __validate_sr(p_rcv, p_madw);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process: "
+ "Component Mask check failed\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ goto Exit;
+ }
+ osm_sr_rcv_process_delete_method(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_GET:
+ case IB_MAD_METHOD_GETTABLE:
+ osm_sr_rcv_process_get_method(p_rcv, p_madw);
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process: "
+ "Bad Method (%s)\n", ib_get_sa_method_str( p_sa_mad->method ));
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+ break;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_sr_rcv_lease_cb(
+ IN void* context )
+{
+ osm_sr_rcv_t* p_rcv = (osm_sr_rcv_t*)context;
+ cl_list_item_t* p_list_item;
+ cl_list_item_t* p_next_list_item;
+ osm_svcr_t* p_svcr;
+ uint32_t curr_time;
+ uint32_t elapsed_time;
+ uint32_t trim_time = 20; /* maxiaml timer refresh is 20 seconds */
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_lease_cb );
+
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ p_list_item = cl_qlist_head(&p_rcv->p_subn->sa_sr_list);
+
+ while( p_list_item != cl_qlist_end(&p_rcv->p_subn->sa_sr_list) )
+ {
+ p_svcr = (osm_svcr_t*)p_list_item;
+
+ if(p_svcr->service_record.service_lease == 0xFFFFFFFF)
+ {
+ p_list_item = cl_qlist_next(p_list_item);
+ continue;
+ }
+
+ /* current time in seconds */
+ curr_time = cl_get_time_stamp_sec();
+ /* elapsed time from last modify */
+ elapsed_time = curr_time - p_svcr->modified_time;
+ /* but it can not be less then 1 */
+ if (elapsed_time < 1) elapsed_time = 1;
+
+ if(elapsed_time < p_svcr->lease_period)
+ {
+ /*
+ Just update the service lease period
+ note: for simplicity we work with a uint32_t field
+ external to the network order lease_period of the MAD
+ */
+ p_svcr->lease_period -= elapsed_time;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_lease_cb: "
+ "Remaining time for Service Name:%s is:0x%X \n",
+ p_svcr->service_record.service_name,
+ p_svcr->lease_period);
+
+ p_svcr->modified_time = curr_time;
+
+ /* Update the trim timer */
+ if(trim_time > p_svcr->lease_period)
+ {
+ trim_time = p_svcr->lease_period;
+ if (trim_time < 1) trim_time = 1;
+ }
+
+ p_list_item = cl_qlist_next(p_list_item);
+ continue;
+
+ }
+ else
+ {
+ p_next_list_item = cl_qlist_next(p_list_item);
+
+ /* Remove the service Record */
+ osm_svcr_remove_from_db(p_rcv->p_subn,
+ p_rcv->p_log,
+ p_svcr);
+
+ osm_svcr_destroy(p_svcr);
+
+ p_list_item = p_next_list_item;
+ continue;
+ }
+ }
+
+ /* Release the Lock */
+ cl_plock_release(p_rcv->p_lock);
+
+ if(trim_time != 0xFFFFFFFF)
+ {
+ cl_timer_trim(&p_rcv->sr_timer,
+ trim_time * 1000 ); /* Convert to milli seconds */
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sr_rcv_ctrl_t.
+ * This object represents the ServiceRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_sr_rcv_process( ((osm_sr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_construct(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_destroy(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_ctrl_init(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl,
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sr_rcv_ctrl_init );
+
+ osm_sr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SERVICE_RECORD,
+ __osm_sr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_ctrl_init: ERR 2501: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rec_rcv_t.
+ * This object represents the SLtoVL Mapping Query Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_slvl_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SLVL_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_SLVL_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_slvl_item
+{
+ cl_pool_item_t pool_item;
+ ib_slvl_table_record_t rec;
+
+} osm_slvl_item_t;
+
+typedef struct _osm_slvl_search_ctxt
+{
+ const ib_slvl_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ uint8_t in_port_num;
+ cl_qlist_t* p_list;
+ osm_slvl_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+
+} osm_slvl_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_construct(
+ IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_destroy(
+ IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_init );
+
+ osm_slvl_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_SLVL_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SLVL_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_slvl_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_create(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN osm_slvl_search_ctxt_t* const p_ctxt,
+ IN uint8_t in_port_idx)
+{
+ osm_slvl_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_create );
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ p_rec_item = (osm_slvl_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_slvl_create: ERR 2602: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_slvl_create: "
+ "New SLtoVL Map for: OUT port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X to In Port:%u.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+ in_port_idx
+ );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.out_port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.in_port_num = in_port_idx;
+ p_rec_item->rec.slvl_tbl = *(osm_physp_get_slvl_tbl(p_physp,in_port_idx));
+
+ cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_slvl_search_ctxt_t* const p_ctxt )
+{
+ const ib_slvl_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ const osm_physp_t* p_out_physp, *p_in_physp;
+ uint8_t in_port_num, out_port_num;
+ uint8_t num_ports;
+ uint8_t in_port_start, in_port_end;
+ uint8_t out_port_start, out_port_end;
+ const osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ num_ports = osm_port_get_num_physp( p_port );
+ in_port_start = 0; in_port_end = num_ports;
+ out_port_start = 0; out_port_end = num_ports;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_slvl_by_comp_mask: "
+ "Using Physical Default Port Number: 0x%X (for End Node).\n",
+ p_port->default_port_num);
+ p_out_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+ /* check that the p_out_physp and the p_req_physp share a pkey */
+ if (osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_out_physp))
+ __osm_sa_slvl_create(p_rcv, p_out_physp, p_ctxt, 0);
+ }
+ else
+ {
+ if ( comp_mask & IB_SLVL_COMPMASK_OUT_PORT )
+ {
+ out_port_start = out_port_end = p_rcvd_rec->out_port_num;
+ }
+ if ( comp_mask & IB_SLVL_COMPMASK_IN_PORT )
+ {
+ in_port_start = in_port_end = p_rcvd_rec->in_port_num;
+ }
+
+
+ for( out_port_num = out_port_start; out_port_num <= out_port_end; out_port_num++ ) {
+ p_out_physp = osm_port_get_phys_ptr( p_port, out_port_num );
+ if( p_out_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_out_physp ) )
+ continue;
+
+ for( in_port_num = in_port_start; in_port_num <= in_port_end; in_port_num++ ) {
+ /* if (out_port_num && out_port_num == in_port_num) */
+ /* continue; */
+
+ p_in_physp = osm_port_get_phys_ptr( p_port, in_port_num );
+ if( p_in_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_in_physp ) )
+ continue;
+
+ /* if the requestor and the p_out_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_out_physp ) )
+ continue;
+
+ __osm_sa_slvl_create(p_rcv, p_out_physp, p_ctxt, in_port_num);
+ }
+ }
+ }
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_slvl_search_ctxt_t* const p_ctxt = (osm_slvl_search_ctxt_t *)context;
+
+ __osm_sa_slvl_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_process(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_slvl_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_slvl_table_t* p_slvl_tbl;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_slvl_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_slvl_search_ctxt_t context;
+ osm_slvl_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_slvl_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+ comp_mask = p_rcvd_mad->comp_mask;
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SLVL_RECORD );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2603: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2604: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ p_slvl_tbl = (ib_slvl_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ cl_qlist_init( &rec_list );
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.in_port_num = p_rcvd_rec->in_port_num;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_slvl_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%02X), In-Port:0x%02X(%02X), Out-Port:0x%02X(%02X).\n",
+ cl_ntoh16(p_rcvd_rec->lid), (comp_mask &IB_SLVL_COMPMASK_LID) != 0,
+ p_rcvd_rec->in_port_num, (comp_mask &IB_SLVL_COMPMASK_IN_PORT) != 0,
+ p_rcvd_rec->out_port_num, (comp_mask &IB_SLVL_COMPMASK_OUT_PORT) != 0) ;
+
+ /*
+ If the user specified a LID, it obviously narrows our
+ work load, since we don't have to search every port
+ */
+ if( comp_mask & IB_SLVL_COMPMASK_LID )
+ {
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ else
+ { /* port out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: "
+ "Given LID (%u) is out of range:%u.\n",
+ cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+
+ /* if we got a unique port - no need for a port search */
+ if( p_port )
+ /* this does the loop on all the port phys ports */
+ __osm_sa_slvl_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_slvl_by_comp_mask_cb,
+ &context );
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_slvl_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_slvl_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_slvl_rec_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_slvl_rec_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_slvl_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2605: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_slvl_table_record_t) );
+
+ p_resp_rec = (ib_slvl_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2606: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rec_rcv_ctrl_t.
+ * This object represents the SLtoVL Map Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_slvl_rec_rcv_process( ((osm_slvl_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_construct(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_destroy(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_ctrl_init(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_ctrl_init );
+
+ osm_slvl_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SLVL_TBL_RECORD,
+ __osm_slvl_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_ctrl_init: ERR 2701: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_smir_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_sminfo_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_construct(
+ IN osm_smir_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_destroy(
+ IN osm_smir_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_rcv_init(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_smir_rcv_init );
+
+ osm_smir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_process(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sminfo_record_t* p_sminfo_rec;
+ ib_sminfo_record_t* p_resp_sminfo_rec;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ osm_madw_t* p_resp_madw;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+ ib_net64_t local_guid;
+ osm_port_t* local_port;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_sminfo_rec = (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2803: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD );
+
+ if (p_sa_mad->method != IB_MAD_METHOD_GET)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2804: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get(p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ sizeof(ib_sminfo_record_t)+IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2801: "
+ "Unable to acquire response MAD.\n" );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+ p_resp_sminfo_rec =
+ (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ p_resp_sminfo_rec->resv0 = 0;
+
+ /* HACK: This handling is incorrect. The record to return is
+ records of known SMs by our SM, and not just the details of
+ our SM. */
+ /* check a matching of pkeys with the local physp the sm is on. */
+ local_guid = p_rcv->p_subn->sm_port_guid;
+ local_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, local_guid );
+ if (FALSE ==
+ osm_physp_share_pkey( p_rcv->p_log, p_req_physp,
+ osm_port_get_default_phys_ptr(local_port) ))
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2802: "
+ "Cannot get sminfo record - pkey violation.\n" );
+ goto Exit;
+ }
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* get our local sm_base_lid to send in the sminfo */
+ p_resp_sminfo_rec->lid = p_rcv->p_subn->sm_base_lid;
+ p_resp_sminfo_rec->sm_info.guid = p_rcv->p_subn->sm_port_guid;
+ p_resp_sminfo_rec->sm_info.sm_key = p_rcv->p_subn->opt.sm_key;
+ p_resp_sminfo_rec->sm_info.act_count =
+ cl_ntoh32(p_rcv->p_stats->qp0_mads_sent);
+ p_resp_sminfo_rec->sm_info.pri_state = p_rcv->p_subn->sm_state;
+
+ cl_plock_release( p_rcv->p_lock );
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /* Copy the MAD header back into the response mad */
+ cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_sminfo_record_t) );
+
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if( status != IB_SUCCESS )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2802: "
+ "Error sending MAD (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_smir_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_smir_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_smir_rcv_process( ((osm_smir_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_construct(
+ IN osm_smir_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_destroy(
+ IN osm_smir_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_ctrl_init(
+ IN osm_smir_ctrl_t* const p_ctrl,
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_smir_ctrl_init );
+
+ osm_smir_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SMINFO_RECORD,
+ __osm_smir_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_smir_ctrl_init: ERR 2901: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vlarb_rec_rcv_t.
+ * This object represents the VLArbitrationRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_vlarb_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_VLARB_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_VLARB_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_vl_arb_item
+{
+ cl_pool_item_t pool_item;
+ ib_vl_arb_table_record_t rec;
+
+} osm_vl_arb_item_t;
+
+typedef struct _osm_vl_arb_search_ctxt
+{
+ const ib_vl_arb_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ uint8_t block_num;
+ cl_qlist_t* p_list;
+ osm_vlarb_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+
+} osm_vl_arb_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_construct(
+ IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_destroy(
+ IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_init );
+
+ osm_vlarb_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_VLARB_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_VLARB_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_vl_arb_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_create(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN osm_vl_arb_search_ctxt_t* const p_ctxt,
+ IN uint8_t block)
+{
+ osm_vl_arb_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_create );
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_vl_arb_create: ERR 2A02: "
+ "cl_qlock_pool_get failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_vl_arb_create: "
+ "New VLArbitration for: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X Block:%u.\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+ block
+ );
+ }
+
+ cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.block_num = block;
+ p_rec_item->rec.vl_arb_tbl = *(osm_physp_get_vla_tbl(p_physp, block));
+
+ cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_check_physp(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ osm_vl_arb_search_ctxt_t* const p_ctxt )
+{
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ uint8_t block;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_check_physp );
+
+ /* we got here with the phys port - all is left is to get thr right block */
+ for (block = 1; block <= 4; block++) {
+ if (!(comp_mask & IB_VLA_COMPMASK_BLOCK) || block == p_ctxt->block_num)
+ {
+ __osm_sa_vl_arb_create( p_rcv, p_physp, p_ctxt, block );
+ }
+ }
+
+ /* Exit: */
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_vl_arb_search_ctxt_t* const p_ctxt )
+{
+ const ib_vl_arb_table_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ osm_physp_t * p_physp;
+ uint8_t port_num;
+ uint8_t num_ports;
+ const osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ port_num = p_rcvd_rec->port_num;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ /* if this is a switch port we can search all ports
+ otherwise we must be looking on port 0 */
+ if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ /* we put it in the comp mask and port num */
+ port_num = p_port->default_port_num;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_vl_arb_by_comp_mask: "
+ "Using Physical Default Port Number: 0x%X (for End Node).\n",
+ port_num);
+ comp_mask |= IB_VLA_COMPMASK_OUT_PORT;
+ }
+
+ if( comp_mask & IB_VLA_COMPMASK_OUT_PORT )
+ {
+ if (port_num < osm_port_get_num_physp( p_port ))
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ /* check that the p_physp is valid, and that the requestor
+ and the p_phsyp share a pkey. */
+ if( p_physp && osm_physp_is_valid( p_physp ) &&
+ osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp) )
+ __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_vl_arb_by_comp_mask: ERR 2A03: "
+ "Given Physical Port Number: 0x%X is out of range should be < 0x%X.\n",
+ port_num, osm_port_get_num_physp( p_port ));
+ goto Exit;
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requestor and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+ continue;
+
+ __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_vl_arb_search_ctxt_t* const p_ctxt = (osm_vl_arb_search_ctxt_t *)context;
+
+ __osm_sa_vl_arb_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_process(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_vl_arb_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_vl_arb_table_t* p_vl_arb;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_vl_arb_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_vl_arb_search_ctxt_t context;
+ osm_vl_arb_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_process );
+
+ /* update the requestor physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A04: "
+ "Cannot find requestor physical port. \n" );
+ goto Exit;
+ }
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_vl_arb_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+ comp_mask = p_rcvd_mad->comp_mask;
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_VLARB_RECORD );
+
+ if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+ (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A05: "
+ "Unsupported Method (%s).\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ p_vl_arb = (ib_vl_arb_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ cl_qlist_init( &rec_list );
+
+
+ context.p_rcvd_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.block_num = p_rcvd_rec->block_num;
+ context.p_req_physp = p_req_physp;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_vlarb_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%02X), Port:0x%02X(%02X), Block:0x%02X(%02X).\n",
+ cl_ntoh16(p_rcvd_rec->lid), (comp_mask &IB_VLA_COMPMASK_LID) != 0,
+ p_rcvd_rec->port_num, (comp_mask &IB_VLA_COMPMASK_OUT_PORT) != 0,
+ p_rcvd_rec->block_num, (comp_mask &IB_VLA_COMPMASK_BLOCK) != 0) ;
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /*
+ If the user specified a LID, it obviously narrows our
+ work load, since we don't have to search every port
+ */
+ if( comp_mask & IB_VLA_COMPMASK_LID )
+ {
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ else
+ { /* port out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: "
+ "Given LID (%u) is out of range:%u.\n",
+ cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+
+ /* if we got a unique port - no need for a port search */
+ if( p_port )
+ /* this does the loop on all the port phys ports */
+ __osm_sa_vl_arb_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_vl_arb_by_comp_mask_cb,
+ &context );
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30 :
+ * If we do a SubAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_vl_arb_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_vl_arb_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_vlarb_rec_rcv_process: "
+ "Number of records:%u trimmed to:%u to fit in one MAD.\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_vlarb_rec_rcv_process: "
+ "Returning %u records.\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_vl_arb_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A06: "
+ "osm_mad_pool_get failed.\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+ /*
+ Copy the MAD header back into the response mad.
+ Set the 'R' bit and the payload length,
+ Then copy all records from the list into the response payload.
+ */
+
+ cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+ /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_vl_arb_table_record_t) );
+
+ p_resp_rec = (ib_vl_arb_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+ }
+#else
+ /* forcefully define the packet as RMPP one */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if(status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A07: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vlarb_rec_rcv_ctrl_t.
+ * This object represents the VL Arbitration Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vlarb_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_vlarb_rec_rcv_process( ((osm_vlarb_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_construct(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_destroy(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_ctrl_init(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_ctrl_init );
+
+ osm_vlarb_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_VL_ARB_RECORD,
+ __osm_vlarb_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_ctrl_init: ERR 2B01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of service record functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_service.h>
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_svcr_construct(
+ IN osm_svcr_t* const p_svcr )
+{
+ cl_memclr( p_svcr, sizeof(*p_svcr) );
+}
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_svcr_destroy(
+ IN osm_svcr_t* const p_svcr )
+{
+ cl_free( p_svcr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_init(
+ IN osm_svcr_t* const p_svcr,
+ IN const ib_service_record_t *p_svc_rec )
+{
+ CL_ASSERT( p_svcr );
+
+ p_svcr->modified_time = cl_get_time_stamp_sec();
+ /* p_svcr->svc_id = p_svc_rec->service_id; */
+
+ /* We track the time left for this service in
+ an external field to avoid extra cl_ntoh/hton
+ required for working with the MAD field */
+ p_svcr->lease_period = cl_ntoh32(p_svc_rec->service_lease);
+ p_svcr->service_record = *p_svc_rec;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+osm_svcr_t*
+osm_svcr_new(
+ IN const ib_service_record_t *p_svc_rec )
+{
+ osm_svcr_t* p_svcr;
+
+ CL_ASSERT(p_svc_rec);
+
+ p_svcr = (osm_svcr_t*)cl_malloc( sizeof(*p_svcr) );
+ if( p_svcr )
+ {
+ osm_svcr_construct( p_svcr );
+ osm_svcr_init( p_svcr, p_svc_rec );
+ }
+
+ return( p_svcr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+cl_status_t
+__match_rid_of_svc_rec(
+
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ ib_service_record_t* p_svc_rec = (ib_service_record_t *)context;
+ osm_svcr_t* p_svcr = (osm_svcr_t*)p_list_item;
+ int32_t count;
+
+
+ count = cl_memcmp(
+ &p_svcr->service_record,
+ p_svc_rec,
+ sizeof(p_svc_rec->service_id) +
+ sizeof(p_svc_rec->service_gid) +
+ sizeof(p_svc_rec->service_pkey) );
+
+ if(count == 0)
+ return CL_SUCCESS;
+ else
+ return CL_NOT_FOUND;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+osm_svcr_t*
+osm_svcr_get_by_rid(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log,
+ IN ib_service_record_t* const p_svc_rec )
+{
+ cl_list_item_t* p_list_item;
+ OSM_LOG_ENTER( p_log, osm_svcr_get_by_rid );
+
+ p_list_item = cl_qlist_find_from_head(
+ &p_subn->sa_sr_list,
+ __match_rid_of_svc_rec,
+ p_svc_rec);
+
+ if( p_list_item == cl_qlist_end( &p_subn->sa_sr_list ) )
+ p_list_item = NULL;
+
+ OSM_LOG_EXIT( p_log );
+ return (osm_svcr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_insert_to_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_svcr_t *p_svcr)
+{
+
+ OSM_LOG_ENTER( p_log, osm_svcr_insert_to_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_svcr_insert_to_db: "
+ "Inserting a new Service Record\n");
+
+ cl_qlist_insert_head(&p_subn->sa_sr_list,
+ &p_svcr->list_item);
+
+ OSM_LOG_EXIT( p_log );
+
+}
+
+void
+osm_svcr_remove_from_db(
+ IN osm_subn_t *p_subn,
+ IN osm_log_t *p_log,
+ IN osm_svcr_t *p_svcr)
+{
+ OSM_LOG_ENTER( p_log, osm_svcr_remove_from_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_svcr_remove_from_db: "
+ "Removing Service Record Name:%s ID:0x%016" PRIx64" from Database\n",
+ p_svcr->service_record.service_name, p_svcr->service_record.service_id
+ );
+
+ cl_qlist_remove_item(&p_subn->sa_sr_list,
+ &p_svcr->list_item);
+
+ OSM_LOG_EXIT( p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_slvl_map_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_construct(
+ IN osm_slvl_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_destroy(
+ IN osm_slvl_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_init(
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_slvl_rcv_init );
+
+ osm_slvl_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+void
+osm_slvl_rcv_process(
+ IN const osm_slvl_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_slvl_table_t *p_slvl_tbl;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ osm_slvl_context_t *p_context;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t out_port_num, in_port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_context = osm_madw_get_slvl_context_ptr( p_madw );
+ p_slvl_tbl = (ib_slvl_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+ port_guid = p_context->port_guid;
+ node_guid = p_context->node_guid;
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SLVL_TABLE );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_process: ERR 2C06: "
+ "No Port object for port with GUID = 0x%" PRIx64
+ "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ goto Exit;
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ /* in case of a non switch node the attr modifier should be ignored */
+ if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+ {
+ out_port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod & 0xFF000000);
+ in_port_num = (uint8_t)cl_ntoh32( (p_smp->attr_mod & 0x00FF0000) << 8);
+ p_physp = osm_node_get_physp_ptr( p_node, out_port_num );
+ }
+ else
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ out_port_num = p_port->default_port_num;
+ in_port_num = 0;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to update
+ the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_slvl_rcv_process: "
+ "Got SLtoVL get response in_port_num %u out_port_num %u with GUID = 0x%" PRIx64
+ " for parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ in_port_num, out_port_num,
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ /*
+ Determine if we encountered a new Physical Port.
+ If so, Ignore it.
+ */
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_process: "
+ "Got invalid port number 0x%X.\n",
+ out_port_num );
+ }
+ goto Exit;
+ }
+
+ osm_dump_slvl_map_table( p_rcv->p_log,
+ port_guid, in_port_num,
+ out_port_num, p_slvl_tbl,
+ OSM_LOG_DEBUG );
+
+ osm_physp_set_slvl_tbl( p_physp, p_slvl_tbl, in_port_num);
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rcv_ctrl_t.
+ * This object represents the SLtoVL request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_slvl_rcv_process( ((osm_slvl_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_construct(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_destroy(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_ctrl_init(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rcv_ctrl_init );
+
+ osm_slvl_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SLVL,
+ __osm_slvl_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_ctrl_init: ERR 2D01: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sm_t.
+ * This object represents the SM Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <complib/cl_signal_osd.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_mcm_info.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+#define OSM_SM_INITIAL_TID_VALUE 0x1233
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_sweeper(
+ IN void *p_ptr )
+{
+ ib_api_status_t status;
+ osm_sm_t *const p_sm = ( osm_sm_t * ) p_ptr;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_sweeper );
+
+ if( p_sm->thread_state == OSM_THREAD_STATE_INIT )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_sweeper: " "Masking ^C Signals.\n" );
+ cl_sig_mask_sigint( );
+
+ p_sm->thread_state = OSM_THREAD_STATE_RUN;
+ }
+
+ /* If the sweep interval was updated before - then run only if
+ * it is not zero. */
+ while( p_sm->thread_state == OSM_THREAD_STATE_RUN &&
+ p_sm->p_subn->opt.sweep_interval != 0 )
+ {
+ /* do the sweep only if we are in MASTER state */
+ if( p_sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER ||
+ p_sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+ osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+
+ /*
+ * Wait on the event with a timeout.
+ * Sweeps may be iniated "off schedule" by simply
+ * signaling the event.
+ */
+ status = cl_event_wait_on( &p_sm->signal,
+ p_sm->p_subn->opt.sweep_interval * 1000000,
+ TRUE );
+
+ if( status == CL_SUCCESS )
+ {
+ if( osm_log_is_active( p_sm->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_sweeper: " "Off schedule sweep signalled.\n" );
+ }
+ }
+ else
+ {
+ if( status != CL_TIMEOUT )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "__osm_sm_sweeper: ERR 2E01: "
+ "Event wait failed (%s).\n", CL_STATUS_MSG( status ) );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_construct(
+ IN osm_sm_t * const p_sm )
+{
+ cl_memclr( p_sm, sizeof( *p_sm ) );
+ p_sm->thread_state = OSM_THREAD_STATE_NONE;
+ p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE;
+ cl_event_construct( &p_sm->signal );
+ cl_event_construct( &p_sm->subnet_up_event );
+ cl_thread_construct( &p_sm->sweeper );
+ osm_req_construct( &p_sm->req );
+ osm_req_ctrl_construct( &p_sm->req_ctrl );
+ osm_resp_construct( &p_sm->resp );
+ osm_ni_rcv_construct( &p_sm->ni_rcv );
+ osm_ni_rcv_ctrl_construct( &p_sm->ni_rcv_ctrl );
+ osm_pi_rcv_construct( &p_sm->pi_rcv );
+ osm_pi_rcv_ctrl_construct( &p_sm->pi_rcv_ctrl );
+ osm_nd_rcv_construct( &p_sm->nd_rcv );
+ osm_nd_rcv_ctrl_construct( &p_sm->nd_rcv_ctrl );
+ osm_sm_mad_ctrl_construct( &p_sm->mad_ctrl );
+ osm_si_rcv_construct( &p_sm->si_rcv );
+ osm_si_rcv_ctrl_construct( &p_sm->si_rcv_ctrl );
+ osm_lid_mgr_construct( &p_sm->lid_mgr );
+ osm_ucast_mgr_construct( &p_sm->ucast_mgr );
+ osm_link_mgr_construct( &p_sm->link_mgr );
+ osm_state_mgr_construct( &p_sm->state_mgr );
+ osm_state_mgr_ctrl_construct( &p_sm->state_mgr_ctrl );
+ osm_drop_mgr_construct( &p_sm->drop_mgr );
+ osm_lft_rcv_construct( &p_sm->lft_rcv );
+ osm_lft_rcv_ctrl_construct( &p_sm->lft_rcv_ctrl );
+ osm_mft_rcv_construct( &p_sm->mft_rcv );
+ osm_mft_rcv_ctrl_construct( &p_sm->mft_rcv_ctrl );
+ osm_sweep_fail_ctrl_construct( &p_sm->sweep_fail_ctrl );
+ osm_sminfo_rcv_construct( &p_sm->sm_info_rcv );
+ osm_sminfo_rcv_ctrl_construct( &p_sm->sm_info_rcv_ctrl );
+ osm_trap_rcv_construct( &p_sm->trap_rcv );
+ osm_trap_rcv_ctrl_construct( &p_sm->trap_rcv_ctrl );
+ osm_sm_state_mgr_construct( &p_sm->sm_state_mgr );
+ osm_slvl_rcv_construct( &p_sm->slvl_rcv );
+ osm_slvl_rcv_ctrl_construct( &p_sm->slvl_rcv_ctrl );
+ osm_vla_rcv_construct( &p_sm->vla_rcv );
+ osm_vla_rcv_ctrl_construct( &p_sm->vla_rcv_ctrl );
+ osm_pkey_rcv_construct( &p_sm->pkey_rcv );
+ osm_pkey_rcv_ctrl_construct( &p_sm->pkey_rcv_ctrl );
+ osm_mcast_mgr_construct( &p_sm->mcast_mgr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_shutdown(
+ IN osm_sm_t * const p_sm )
+{
+ boolean_t signal_event = FALSE;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_shutdown );
+
+ /*
+ * Signal our threads that we're leaving.
+ */
+ if( p_sm->thread_state != OSM_THREAD_STATE_NONE )
+ signal_event = TRUE;
+
+ p_sm->thread_state = OSM_THREAD_STATE_EXIT;
+
+ /*
+ * Don't trigger unless event has been initialized.
+ * Destroy the thread before we tear down the other objects.
+ */
+ if( signal_event )
+ cl_event_signal( &p_sm->signal );
+
+ cl_thread_destroy( &p_sm->sweeper );
+
+ /*
+ * Always destroy controllers before the corresponding
+ * receiver to guarantee that all callbacks from the
+ * dispatcher are complete.
+ */
+ osm_sm_mad_ctrl_destroy( &p_sm->mad_ctrl );
+ osm_trap_rcv_ctrl_destroy( &p_sm->trap_rcv_ctrl );
+ osm_sminfo_rcv_ctrl_destroy( &p_sm->sm_info_rcv_ctrl );
+ osm_req_ctrl_destroy( &p_sm->req_ctrl );
+ osm_ni_rcv_ctrl_destroy( &p_sm->ni_rcv_ctrl );
+ osm_pi_rcv_ctrl_destroy( &p_sm->pi_rcv_ctrl );
+ osm_si_rcv_ctrl_destroy( &p_sm->si_rcv_ctrl );
+ osm_nd_rcv_ctrl_destroy( &p_sm->nd_rcv_ctrl );
+ osm_lft_rcv_ctrl_destroy( &p_sm->lft_rcv_ctrl );
+ osm_mft_rcv_ctrl_destroy( &p_sm->mft_rcv_ctrl );
+ osm_slvl_rcv_ctrl_destroy( &p_sm->slvl_rcv_ctrl );
+ osm_vla_rcv_ctrl_destroy( &p_sm->vla_rcv_ctrl );
+ osm_pkey_rcv_ctrl_destroy( &p_sm->pkey_rcv_ctrl );
+ osm_sweep_fail_ctrl_destroy( &p_sm->sweep_fail_ctrl );
+ osm_state_mgr_ctrl_destroy( &p_sm->state_mgr_ctrl );
+
+ OSM_LOG_EXIT( p_sm->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_destroy(
+ IN osm_sm_t * const p_sm )
+{
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_destroy );
+ osm_trap_rcv_destroy( &p_sm->trap_rcv );
+ osm_sminfo_rcv_destroy( &p_sm->sm_info_rcv );
+ osm_req_destroy( &p_sm->req );
+ osm_resp_destroy( &p_sm->resp );
+ osm_ni_rcv_destroy( &p_sm->ni_rcv );
+ osm_pi_rcv_destroy( &p_sm->pi_rcv );
+ osm_si_rcv_destroy( &p_sm->si_rcv );
+ osm_nd_rcv_destroy( &p_sm->nd_rcv );
+ osm_lid_mgr_destroy( &p_sm->lid_mgr );
+ osm_ucast_mgr_destroy( &p_sm->ucast_mgr );
+ osm_link_mgr_destroy( &p_sm->link_mgr );
+ osm_drop_mgr_destroy( &p_sm->drop_mgr );
+ osm_lft_rcv_destroy( &p_sm->lft_rcv );
+ osm_mft_rcv_destroy( &p_sm->mft_rcv );
+ osm_slvl_rcv_destroy( &p_sm->slvl_rcv );
+ osm_vla_rcv_destroy( &p_sm->vla_rcv );
+ osm_pkey_rcv_destroy( &p_sm->pkey_rcv );
+ osm_state_mgr_destroy( &p_sm->state_mgr );
+ osm_sm_state_mgr_destroy( &p_sm->sm_state_mgr );
+ osm_mcast_mgr_destroy( &p_sm->mcast_mgr );
+ cl_event_destroy( &p_sm->signal );
+ cl_event_destroy( &p_sm->subnet_up_event );
+
+ if( p_sm->p_report_buf != NULL )
+ cl_free( p_sm->p_report_buf );
+
+ osm_log( p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n" ); /* Format Waived */
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_subn_t * const p_subn,
+ IN osm_db_t * const p_db,
+ IN osm_vendor_t * const p_vendor,
+ IN osm_mad_pool_t * const p_mad_pool,
+ IN osm_vl15_t * const p_vl15,
+ IN osm_log_t * const p_log,
+ IN osm_stats_t * const p_stats,
+ IN cl_dispatcher_t * const p_disp,
+ IN cl_plock_t * const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sm_init );
+
+ p_sm->p_subn = p_subn;
+ p_sm->p_db = p_db;
+ p_sm->p_vendor = p_vendor;
+ p_sm->p_mad_pool = p_mad_pool;
+ p_sm->p_vl15 = p_vl15;
+ p_sm->p_log = p_log;
+ p_sm->p_disp = p_disp;
+ p_sm->p_lock = p_lock;
+
+ p_sm->p_report_buf = cl_malloc( OSM_REPORT_BUF_SIZE );
+ if( p_sm->p_report_buf == NULL )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_init: ERR 2E09: " "Can't allocate report buffer.\n" );
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+ status = cl_event_init( &p_sm->signal, FALSE );
+ if( status != CL_SUCCESS )
+ goto Exit;
+
+ status = cl_event_init( &p_sm->subnet_up_event, FALSE );
+ if( status != CL_SUCCESS )
+ goto Exit;
+
+ status = osm_sm_mad_ctrl_init( &p_sm->mad_ctrl,
+ p_sm->p_subn,
+ p_sm->p_mad_pool,
+ p_sm->p_vl15,
+ p_sm->p_vendor,
+ p_log, p_stats, p_lock, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_req_init( &p_sm->req,
+ p_mad_pool,
+ p_vl15, p_subn, p_log, &p_sm->sm_trans_id );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_req_ctrl_init( &p_sm->req_ctrl, &p_sm->req, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_resp_init( &p_sm->resp, p_mad_pool, p_vl15, p_subn, p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ni_rcv_init( &p_sm->ni_rcv,
+ &p_sm->req,
+ p_subn, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ni_rcv_ctrl_init( &p_sm->ni_rcv_ctrl,
+ &p_sm->ni_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pi_rcv_init( &p_sm->pi_rcv,
+ &p_sm->req,
+ p_subn, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pi_rcv_ctrl_init( &p_sm->pi_rcv_ctrl,
+ &p_sm->pi_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_si_rcv_init( &p_sm->si_rcv,
+ p_sm->p_subn,
+ p_sm->p_log,
+ &p_sm->req, &p_sm->state_mgr, p_sm->p_lock );
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_si_rcv_ctrl_init( &p_sm->si_rcv_ctrl,
+ &p_sm->si_rcv, p_sm->p_log, p_sm->p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nd_rcv_init( &p_sm->nd_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nd_rcv_ctrl_init( &p_sm->nd_rcv_ctrl,
+ &p_sm->nd_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lid_mgr_init( &p_sm->lid_mgr,
+ &p_sm->req,
+ p_sm->p_subn,
+ p_sm->p_db, p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ucast_mgr_init( &p_sm->ucast_mgr,
+ &p_sm->req,
+ p_sm->p_subn,
+ p_sm->p_report_buf,
+ p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_link_mgr_init( &p_sm->link_mgr,
+ &p_sm->req,
+ p_sm->p_subn, p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_state_mgr_init( &p_sm->state_mgr,
+ p_sm->p_subn,
+ &p_sm->lid_mgr,
+ &p_sm->ucast_mgr,
+ &p_sm->mcast_mgr,
+ &p_sm->link_mgr,
+ &p_sm->drop_mgr,
+ &p_sm->req,
+ p_stats,
+ &p_sm->sm_state_mgr,
+ &p_sm->mad_ctrl,
+ p_sm->p_lock,
+ &p_sm->subnet_up_event,
+ p_sm->p_report_buf, p_sm->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_state_mgr_ctrl_init( &p_sm->state_mgr_ctrl,
+ &p_sm->state_mgr,
+ p_sm->p_log, p_sm->p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_drop_mgr_init( &p_sm->drop_mgr,
+ p_sm->p_subn,
+ p_sm->p_log, &p_sm->req, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lft_rcv_init( &p_sm->lft_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lft_rcv_ctrl_init( &p_sm->lft_rcv_ctrl,
+ &p_sm->lft_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mft_rcv_init( &p_sm->mft_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mft_rcv_ctrl_init( &p_sm->mft_rcv_ctrl,
+ &p_sm->mft_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sweep_fail_ctrl_init( &p_sm->sweep_fail_ctrl,
+ p_log, &p_sm->state_mgr, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sminfo_rcv_init( &p_sm->sm_info_rcv,
+ p_subn,
+ p_stats,
+ &p_sm->resp,
+ p_log,
+ &p_sm->state_mgr,
+ &p_sm->sm_state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sminfo_rcv_ctrl_init( &p_sm->sm_info_rcv_ctrl,
+ &p_sm->sm_info_rcv,
+ p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_trap_rcv_init( &p_sm->trap_rcv,
+ p_subn,
+ p_stats,
+ &p_sm->resp, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_trap_rcv_ctrl_init( &p_sm->trap_rcv_ctrl,
+ &p_sm->trap_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sm_state_mgr_init( &p_sm->sm_state_mgr,
+ &p_sm->state_mgr,
+ p_sm->p_subn, &p_sm->req, p_sm->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcast_mgr_init( &p_sm->mcast_mgr,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rcv_init( &p_sm->slvl_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rcv_ctrl_init( &p_sm->slvl_rcv_ctrl,
+ &p_sm->slvl_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vla_rcv_init( &p_sm->vla_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vla_rcv_ctrl_init( &p_sm->vla_rcv_ctrl,
+ &p_sm->vla_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rcv_init( &p_sm->pkey_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rcv_ctrl_init( &p_sm->pkey_rcv_ctrl,
+ &p_sm->pkey_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+
+ /*
+ * Now that the component objects are initialized, start
+ * the sweeper thread if the user wants sweeping.
+ */
+ if( p_sm->p_subn->opt.sweep_interval )
+ {
+ p_sm->thread_state = OSM_THREAD_STATE_INIT;
+ status = cl_thread_init( &p_sm->sweeper, __osm_sm_sweeper, p_sm,
+ "opensm sweeper" );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_sweep(
+ IN osm_sm_t * const p_sm )
+{
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_sweep );
+ osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_bind(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_bind );
+
+ status = osm_sm_mad_ctrl_bind( &p_sm->mad_ctrl, port_guid );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_bind: ERR 2E10: "
+ "SM MAD Controller bind() failed (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sm_mgrp_connect(
+ IN osm_sm_t * const p_sm,
+ IN osm_mgrp_t * const p_mgrp,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type )
+{
+ ib_api_status_t status;
+ osm_mcast_mgr_ctxt_t *ctx2;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_connect );
+
+ /*
+ * 'Schedule' all the QP0 traffic for when the state manager
+ * isn't busy trying to do something else.
+ */
+ ctx2 =
+ ( osm_mcast_mgr_ctxt_t * ) cl_malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+ cl_memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+ ctx2->req_type = req_type;
+ ctx2->port_guid = port_guid;
+
+ status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+ osm_mcast_mgr_process_mgrp_cb,
+ NULL, &p_sm->mcast_mgr,
+ ( void * )ctx2 );
+
+ /* Exit: */
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_mgrp_disconnect(
+ IN osm_sm_t * const p_sm,
+ IN osm_mgrp_t * const p_mgrp,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+ osm_mcast_mgr_ctxt_t *ctx2;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_disconnect );
+
+ /*
+ * 'Schedule' all the QP0 traffic for when the state manager
+ * isn't busy trying to do something else.
+ */
+ ctx2 =
+ ( osm_mcast_mgr_ctxt_t * ) cl_malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+ cl_memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+ ctx2->req_type = OSM_MCAST_REQ_TYPE_LEAVE;
+ ctx2->port_guid = port_guid;
+
+ status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+ osm_mcast_mgr_process_mgrp_cb,
+ NULL, &p_sm->mcast_mgr, ctx2 );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mgrp_disconnect: ERR 2E11: "
+ "Failure processing multicast group (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_join(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type )
+{
+ osm_mgrp_t *p_mgrp;
+ osm_port_t *p_port;
+ cl_qmap_t *p_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_mcm_info_t *p_mcm;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_join );
+
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_join: "
+ "Port 0x%016" PRIx64 " joining MLID 0x%X.\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+ /*
+ * Acquire the port object for the port joining this group.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_sm->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E05: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * If this multicast group does not already exist, create it.
+ */
+ p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+ p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+ if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_join: "
+ "Creating group, MLID 0x%X.\n", cl_ntoh16( mlid ) );
+
+ p_mgrp = osm_mgrp_new( mlid );
+ if( p_mgrp == NULL )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E06: "
+ "Unable to allocate multicast group object.\n" );
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ cl_qmap_insert( p_tbl, mlid, &p_mgrp->map_item );
+ }
+ else
+ {
+ /*
+ * The group already exists. If the port is not a
+ * member of the group, then fail immediately.
+ * This can happen since the spinlock is released briefly
+ * before the SA calls this function.
+ */
+ if( !osm_mgrp_is_guid( p_mgrp, port_guid ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E12: "
+ "Port 0x%016" PRIx64 " not in mcast group 0x%X.\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+ goto Exit;
+ }
+ }
+
+ /*
+ * Check if the object (according to mlid) already exists on this port.
+ * If it does - then no need to update it again, and no need to
+ * create the mc tree again. Just goto Exit.
+ */
+ p_mcm = ( osm_mcm_info_t * ) cl_qlist_head( &p_port->mcm_list );
+ while( p_mcm != ( osm_mcm_info_t * ) cl_qlist_end( &p_port->mcm_list ) )
+ {
+ if( p_mcm->mlid == mlid )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+ "osm_sm_mcgrp_join: "
+ "Found mlid object for Port:"
+ "0x%016" PRIx64 " lid:0x%X\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+ goto Exit;
+ }
+ p_mcm = ( osm_mcm_info_t * ) cl_qlist_next( &p_mcm->list_item );
+ }
+
+ status = osm_port_add_mgrp( p_port, mlid );
+ if( status != IB_SUCCESS )
+ {
+ cl_plock_release( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E03: "
+ "Unable to associate port 0x%" PRIx64 " to mlid 0x%X.\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+ goto Exit;
+ }
+
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ status = __osm_sm_mgrp_connect( p_sm, p_mgrp, port_guid, req_type );
+
+ Exit:
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid )
+{
+ osm_mgrp_t *p_mgrp;
+ osm_port_t *p_port;
+ cl_qmap_t *p_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_leave );
+
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_leave: "
+ "Port 0x%" PRIx64 " leaving MLID 0x%X.\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+ /*
+ * Acquire the port object for the port leaving this group.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_sm->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_leave: ERR 2E04: "
+ "No port object for port 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * Get the multicast group object for this group.
+ */
+ p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+ p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+ if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_leave: ERR 2E08: "
+ "No multicast group for MLID 0x%X.\n", cl_ntoh16( mlid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * Walk the list of ports in the group, and remove the appropriate one.
+ */
+ osm_mgrp_remove_port( p_sm->p_subn, p_sm->p_log, p_mgrp, port_guid );
+
+ osm_port_remove_mgrp( p_port, mlid );
+
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+
+ __osm_sm_mgrp_disconnect( p_sm, p_mgrp, port_guid );
+
+ Exit:
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sm_mad_ctrl_t.
+ * This object represents the SM MAD request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad
+ * NAME
+ * __osm_sm_mad_ctrl_retire_trans_mad
+ *
+ * DESCRIPTION
+ * This function handles clean-up of MADs associated with the SM's
+ * outstanding transactions on the wire.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_retire_trans_mad(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t* const p_madw )
+{
+ uint32_t outstanding;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_retire_trans_mad );
+
+ CL_ASSERT( p_madw );
+ /*
+ Return the MAD & wrapper to the pool.
+ */
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "Retiring MAD with TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_madw_get_smp_ptr( p_madw )->trans_id ) );
+ }
+
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+
+ cl_atomic_dec( &p_ctrl->p_stats->qp0_mads_outstanding );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "%u QP0 MADs outstanding.\n",
+ p_ctrl->p_stats->qp0_mads_outstanding );
+ }
+
+ /*
+ Acquire the lock non-exclusively.
+ Other modules that send MADs grab this lock exclusively.
+ These modules that are in the process of sending MADs
+ will hold the lock until they finish posting all the MADs
+ they plan to send. While the other module is sending MADs
+ the outstanding count may temporarily go to zero.
+ Thus, by grabbing the lock ourselves, we get an accurate
+ view of whether or not the number of outstanding MADs is
+ really zero.
+ */
+ CL_PLOCK_ACQUIRE( p_ctrl->p_lock );
+ outstanding = p_ctrl->p_stats->qp0_mads_outstanding;
+ CL_PLOCK_RELEASE( p_ctrl->p_lock );
+
+ if( outstanding == 0 )
+ {
+ /*
+ The wire is clean.
+ Signal the state manager.
+ */
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS,
+ NULL,
+ NULL );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_retire_trans_mad: ERR 3101: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_sm_mad_ctrl_disp_done_callback
+ *
+ * DESCRIPTION
+ * This function is the Dispatcher callback that indicates
+ * a received MAD has been processed by the recipient.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_disp_done_callback(
+ IN void* context,
+ IN void* p_data )
+{
+ osm_sm_mad_ctrl_t* const p_ctrl = (osm_sm_mad_ctrl_t*)context;
+ osm_madw_t* const p_madw = (osm_madw_t*)p_data;
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_disp_done_callback );
+
+ /*
+ If the MAD that just finished processing was a response,
+ then retire the transaction, since we must have generated
+ the request.
+
+ Otherwise, retire the transaction if a response was expected,
+ as in the case of a send failure. If a response was not expected,
+ just put the MAD back in the pool, because the MAD was a query
+ from some outside agent, e.g. Get(SMInfo) from another SM.
+ */
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ if( ib_smp_is_response( p_smp ) )
+ {
+ CL_ASSERT( p_madw->resp_expected == FALSE );
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ }
+ else
+ {
+ if( p_madw->resp_expected == TRUE )
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ else
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats
+ * NAME
+ * __osm_sm_mad_ctrl_update_wire_stats
+ *
+ * DESCRIPTION
+ * Updates wire stats for outstanding MADs and calls the VL15 poller.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_update_wire_stats(
+ IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+ uint32_t mads_on_wire;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_update_wire_stats );
+
+ mads_on_wire = cl_atomic_dec(
+ &p_ctrl->p_stats->qp0_mads_outstanding_on_wire );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_update_wire_stats: "
+ "%u SMPs on the wire, %u outstanding.\n", mads_on_wire,
+ p_ctrl->p_stats->qp0_mads_outstanding );
+ }
+
+ /*
+ We can signal the VL15 controller to send another MAD
+ if any are waiting for transmission.
+ */
+ osm_vl15_poll( p_ctrl->p_vl15 );
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp
+ * NAME
+ * __osm_sm_mad_ctrl_process_get_resp
+ *
+ * DESCRIPTION
+ * This function handles method GetResp() for received MADs.
+ * This is the most common path for QP0 MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_get_resp(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw,
+ IN void* transaction_context )
+{
+ ib_smp_t* p_smp;
+ cl_status_t status;
+ osm_madw_t* p_old_madw;
+ cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get_resp );
+
+ CL_ASSERT( p_madw );
+ CL_ASSERT( transaction_context );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( !ib_smp_is_d( p_smp ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3102: "
+ "'D' bit not set in returned SMP.\n" );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ }
+
+ p_old_madw = (osm_madw_t*)transaction_context;
+
+ __osm_sm_mad_ctrl_update_wire_stats( p_ctrl );
+
+ /*
+ Copy the MAD Wrapper context from the requesting MAD
+ to the new MAD. This mechanism allows the recipient
+ controller to recover its own context regarding this
+ MAD transaction. Once we've copied the context, we
+ can return the original MAD to the pool.
+ */
+ osm_madw_copy_context( p_madw, p_old_madw );
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_old_madw );
+
+ /*
+ Note that attr_id (like the rest of the MAD) is in
+ network byte order.
+ */
+ switch( p_smp->attr_id )
+ {
+ case IB_MAD_ATTR_NODE_DESC:
+ msg_id = OSM_MSG_MAD_NODE_DESC;
+ break;
+ case IB_MAD_ATTR_NODE_INFO:
+ msg_id = OSM_MSG_MAD_NODE_INFO;
+ break;
+ case IB_MAD_ATTR_SWITCH_INFO:
+ msg_id = OSM_MSG_MAD_SWITCH_INFO;
+ break;
+ case IB_MAD_ATTR_PORT_INFO:
+ msg_id = OSM_MSG_MAD_PORT_INFO;
+ break;
+ case IB_MAD_ATTR_LIN_FWD_TBL:
+ msg_id = OSM_MSG_MAD_LFT;
+ break;
+ case IB_MAD_ATTR_MCAST_FWD_TBL:
+ msg_id = OSM_MSG_MAD_MFT;
+ break;
+ case IB_MAD_ATTR_SM_INFO:
+ msg_id = OSM_MSG_MAD_SM_INFO;
+ break;
+ case IB_MAD_ATTR_SLVL_TABLE:
+ msg_id = OSM_MSG_MAD_SLVL;
+ break;
+ case IB_MAD_ATTR_VL_ARBITRATION:
+ msg_id = OSM_MSG_MAD_VL_ARB;
+ break;
+ case IB_MAD_ATTR_P_KEY_TABLE:
+ msg_id = OSM_MSG_MAD_PKEY;
+ break;
+
+ case IB_MAD_ATTR_GUID_INFO:
+ case IB_MAD_ATTR_CLASS_PORT_INFO:
+ case IB_MAD_ATTR_NOTICE:
+ case IB_MAD_ATTR_INFORM_INFO:
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3103: "
+ "Unsupported attribute = 0x%X.\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ goto Exit;
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_get_resp: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3104: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ We received a response for which there is no recipient!!
+ */
+ CL_ASSERT( FALSE );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_get
+ * NAME
+ * __osm_sm_mad_ctrl_process_get
+ *
+ * DESCRIPTION
+ * This function handles method Get() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_get(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw )
+{
+ ib_smp_t* p_smp;
+ cl_status_t status;
+ cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ Note that attr_id (like the rest of the MAD) is in
+ network byte order.
+ */
+ switch( p_smp->attr_id )
+ {
+ case IB_MAD_ATTR_SM_INFO:
+ msg_id = OSM_MSG_MAD_SM_INFO;
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_mad_ctrl_process_get: "
+ "Ignoring SubnGet MAD - unsupported attribute = 0x%X.\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_get: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get: ERR 3106: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is a known MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_set
+ * NAME
+ * __osm_sm_mad_ctrl_process_set
+ *
+ * DESCRIPTION
+ * This function handles method Set() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_set(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw )
+{
+ ib_smp_t* p_smp;
+ cl_status_t status;
+ cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_set );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ Note that attr_id (like the rest of the MAD) is in
+ network byte order.
+ */
+ switch( p_smp->attr_id )
+ {
+ case IB_MAD_ATTR_SM_INFO:
+ msg_id = OSM_MSG_MAD_SM_INFO;
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_set: ERR 3107: "
+ "Unsupported attribute = 0x%X.\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_set: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_set: ERR 3108: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is a known MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap
+ * NAME
+ * __osm_sm_mad_ctrl_process_trap
+ *
+ * DESCRIPTION
+ * This function handles method Trap() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_trap(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw )
+{
+ ib_smp_t* p_smp;
+ cl_status_t status;
+ cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_trap );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /* Make sure OpenSM is master. If not - then we should not process the trap */
+ if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_trap: "
+ "Received trap but OpenSM is not in MASTER state. "
+ "Dropping mad. \n");
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+
+ /*
+ Note that attr_id (like the rest of the MAD) is in
+ network byte order.
+ */
+ switch( p_smp->attr_id )
+ {
+ case IB_MAD_ATTR_NOTICE:
+ msg_id = OSM_MSG_MAD_NOTICE;
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_trap: ERR 3109: "
+ "Unsupported attribute = 0x%X.\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_trap: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_trap: ERR 3110: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is a known MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sm_mad_ctrl_rcv_callback(
+ IN osm_madw_t *p_madw,
+ IN void *bind_context,
+ IN osm_madw_t *p_req_madw )
+{
+ osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context;
+ ib_smp_t* p_smp;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_rcv_callback );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ A MAD was received from the wire, possibly in response to a request.
+ */
+ cl_atomic_inc( &p_ctrl->p_stats->qp0_mads_rcvd );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_rcv_callback: "
+ "%u QP0 MADs received.\n",
+ p_ctrl->p_stats->qp0_mads_rcvd );
+ }
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /* if we are closing down simply do nothing */
+ if (osm_exit_flag)
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_rcv_callback: "
+ "Ignoring received mad - since we are exiting.\n");
+
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_DEBUG );
+
+ /* retire the mad or put it back */
+ if( ib_smp_is_response( p_smp ) ||
+ (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS))
+ {
+ CL_ASSERT( p_madw->resp_expected == FALSE );
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ }
+ else
+ {
+ if( p_madw->resp_expected == TRUE )
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ else
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ }
+
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_FRAMES );
+
+ if( ib_smp_get_status( p_smp ) != 0 )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_rcv_callback: ERR 3111: "
+ "Error status = 0x%X.\n", ib_smp_get_status( p_smp ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ }
+
+ switch( p_smp->method )
+ {
+ case IB_MAD_METHOD_GET_RESP:
+ CL_ASSERT( p_req_madw != NULL );
+ __osm_sm_mad_ctrl_process_get_resp( p_ctrl,
+ p_madw, p_req_madw );
+ break;
+
+ case IB_MAD_METHOD_GET:
+ CL_ASSERT( p_req_madw == NULL );
+ __osm_sm_mad_ctrl_process_get( p_ctrl, p_madw );
+ break;
+
+ case IB_MAD_METHOD_TRAP:
+ CL_ASSERT( p_req_madw == NULL );
+ __osm_sm_mad_ctrl_process_trap( p_ctrl, p_madw );
+ break;
+
+ case IB_MAD_METHOD_SET:
+ CL_ASSERT( p_req_madw == NULL );
+ __osm_sm_mad_ctrl_process_set( p_ctrl, p_madw );
+ break;
+ case IB_MAD_METHOD_SEND:
+ case IB_MAD_METHOD_REPORT:
+ case IB_MAD_METHOD_REPORT_RESP:
+ case IB_MAD_METHOD_TRAP_REPRESS:
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_rcv_callback: ERR 3112: "
+ "Unsupported method = 0x%X.\n", p_smp->method );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb
+ * NAME
+ * __osm_sm_mad_ctrl_send_err_cb
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for send errors
+ * on MADs that were expecting a response.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sm_mad_ctrl_send_err_cb(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context;
+ osm_physp_t* p_physp;
+ ib_api_status_t status;
+ ib_smp_t* p_smp;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_send_err_cb );
+
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3113: "
+ "MAD completed in error (%s).\n",
+ ib_get_err_str( p_madw->status ) );
+
+ CL_ASSERT( p_madw );
+ CL_ASSERT( p_madw->resp_expected == TRUE );
+
+ /*
+ If this was a SubnSet mad, then this error might indicate a problem
+ in configuring the subnet. In this case - need to mark that there was
+ such a problem. The subnet will not be up, and the next sweep should
+ be a heavy sweep as well.
+ */
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ if (p_smp->method == IB_MAD_METHOD_SET &&
+ ( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
+ p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
+ p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
+ p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3119: "
+ "Set method failed.\n" );
+ p_ctrl->p_subn->subnet_initialization_error = TRUE;
+ }
+
+ /*
+ Since we did not get any response we suspect the DR path
+ used for the target port.
+ Find it and replace it with an alternate path.
+ This is true only if the destination lid is not 0xFFFF, since
+ then we are aiming for a specific path and not specific destination
+ lid.
+ */
+ /* For now - do not add the alternate dr path to the release */
+ if (0)
+ if ( p_madw->mad_addr.dest_lid != 0xFFFF )
+ {
+ p_physp =
+ osm_get_physp_by_mad_addr(p_ctrl->p_log,
+ p_ctrl->p_subn,
+ &(p_madw->mad_addr));
+ if (! p_physp)
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3114: "
+ "Fail to find the corresponding phys port.\n");
+ }
+ else
+ {
+ osm_physp_replace_dr_path_with_alternate_dr_path(
+ p_ctrl->p_log, p_ctrl->p_subn, p_physp, p_madw->h_bind );
+ }
+ }
+
+ /*
+ An error occurred. No response was received to a request MAD.
+ Retire the original request MAD.
+ */
+
+ osm_dump_dr_smp( p_ctrl->p_log, osm_madw_get_smp_ptr( p_madw ),
+ OSM_LOG_ERROR );
+
+ __osm_sm_mad_ctrl_update_wire_stats( p_ctrl );
+
+ if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+ {
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_send_err_cb: "
+ "Posting Dispatcher message %s.\n",
+ osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ osm_madw_get_err_msg( p_madw ),
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3115: "
+ "Dispatcher post message failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+ else
+ {
+ /*
+ No error message was provided, just retire the MAD.
+ */
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ }
+
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_mad_ctrl_construct(
+ IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_mad_ctrl_destroy(
+ IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+
+ if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE)
+ {
+ osm_vendor_unbind( p_ctrl->h_bind );
+ }
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mad_ctrl_init(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sm_mad_ctrl_init );
+
+ osm_sm_mad_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_subn = p_subn;
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_mad_pool = p_mad_pool;
+ p_ctrl->p_vendor = p_vendor;
+ p_ctrl->p_stats = p_stats;
+ p_ctrl->p_lock = p_lock;
+ p_ctrl->p_vl15 = p_vl15;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ CL_DISP_MSGID_NONE,
+ NULL,
+ NULL );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sm_mad_ctrl_init: ERR 3116: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mad_ctrl_bind(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN const ib_net64_t port_guid )
+{
+ osm_bind_info_t bind_info;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, osm_sm_mad_ctrl_bind );
+
+ if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sm_mad_ctrl_bind: ERR 3117: "
+ "Multiple binds not allowed. Call unbind first. " );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ bind_info.class_version = 1;
+ bind_info.is_report_processor = FALSE;
+ bind_info.is_responder = TRUE;
+ bind_info.is_trap_processor = TRUE;
+ bind_info.mad_class = IB_MCLASS_SUBN_DIR;
+ bind_info.port_guid = port_guid;
+ bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+ bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mad_ctrl_bind: "
+ "Binding to port 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+
+ p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor,
+ &bind_info,
+ p_ctrl->p_mad_pool,
+ __osm_sm_mad_ctrl_rcv_callback,
+ __osm_sm_mad_ctrl_send_err_cb,
+ p_ctrl );
+
+ if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ status = IB_ERROR;
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sm_mad_ctrl_bind: ERR 3118: "
+ "Vendor specific bind() failed.\n" );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_t.
+ * This file implements the Discovery Done Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <time.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_standby_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering STANDBY state" ); /* Format Waived */
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_standby_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM STANDBY"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_master_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_master_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM MASTER"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_discovering_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_discovering_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM DISCOVERING"
+ " STATE ***************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_notactive_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_notactive_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM NOT-ACTIVE"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_send_local_port_info_req(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_madw_context_t context;
+ osm_port_t *p_port;
+ ib_net64_t port_guid = p_sm_mgr->p_subn->sm_port_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log,
+ __osm_sm_state_mgr_send_local_port_info_req );
+ /*
+ * Send a query of SubnGet(PortInfo) to our own port, in order to
+ * update the master_sm_base_lid of the subnet.
+ */
+ cl_memclr( &context, sizeof( context ) );
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm_mgr->p_subn->port_guid_tbl ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_local_port_info_req: ERR 3205: "
+ "No port object for port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( port_guid ) );
+ goto Exit;
+ }
+
+ context.pi_context.port_guid = port_guid;
+ context.pi_context.node_guid = p_port->p_node->node_info.node_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ /* mark the update_master_sm_base_lid with TRUE - we want to update it */
+ /* with the new master lid value. */
+ context.pi_context.update_master_sm_base_lid = TRUE;
+ context.pi_context.light_sweep = FALSE;
+
+ status = osm_req_get( p_sm_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( p_port->default_port_num ),
+ CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_local_port_info_req: ERR 3202: "
+ "Failure requesting PortInfo (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_send_master_sm_info_req(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_madw_context_t context;
+ const osm_port_t *p_port;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log,
+ __osm_sm_state_mgr_send_master_sm_info_req );
+
+ cl_memclr( &context, sizeof( context ) );
+ if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY )
+ {
+ /*
+ * We are in STANDBY state - this means we need to poll on the master
+ * SM (according to master_guid)
+ * Send a query of SubnGet(SMInfo) to the subn master_sm_base_lid object.
+ */
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+ p_sm_mgr->master_guid );
+ }
+ else
+ {
+ /*
+ * We are not in STANDBY - this means we are in MASTER state - so we need
+ * to poll on the SM that is saved in p_polling_sm under p_sm_mgr.
+ * Send a query of SubnGet(SMInfo) to that SM.
+ */
+ p_port = p_sm_mgr->p_polling_sm->p_port;
+ }
+ if( p_port == NULL )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3203: "
+ "No port object for guid 0x%X \n", p_sm_mgr->master_guid );
+ goto Exit;
+ }
+
+ context.smi_context.port_guid = p_port->guid;
+ context.smi_context.set_method = FALSE;
+
+ status = osm_req_get( p_sm_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ),
+ IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3204: "
+ "Failure rquesting SMInfo (%s).\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_start_polling(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ uint32_t sminfo_polling_timeout =
+ p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_start_polling );
+
+ /*
+ * Init the retry_nubmer back to zero - need to restart counting
+ */
+ p_sm_mgr->retry_number = 0;
+
+ /*
+ * Send a SubnGet(SMInfo) query to the found current (or new) master.
+ */
+ __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+ /*
+ * Start a timer that will wake up every sminfo_polling_timeout milliseconds.
+ * The callback of the timer will send a SubnGet(SMInfo) to the Master SM,
+ * and restart the timer
+ */
+ cl_status = cl_timer_start( &p_sm_mgr->polling_timer,
+ sminfo_polling_timeout );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_start_polling : ERROR 1000: "
+ "Failed to start timer\n" );
+ }
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_polling_callback(
+ IN void *context )
+{
+ osm_sm_state_mgr_t *p_sm_mgr = ( osm_sm_state_mgr_t * ) context;
+ uint32_t sminfo_polling_timeout =
+ p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_polling_callback );
+
+ /*
+ * We can be here in one of two cases:
+ * 1. We are a STANDBY sm polling on the master SM.
+ * 2. We are a MASTER sm, waiting for a handover from a remote master sm.
+ * If we are not in one of these cases - don't need to restart the poller.
+ */
+ if( !( ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER &&
+ p_sm_mgr->p_polling_sm != NULL ) ||
+ ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY ) ) )
+ {
+ goto Exit;
+ }
+
+ /*
+ * If we are a STANDBY sm, and the osm_exit_flag is 1, then let's signal
+ * the subnet_up. This is relevant for the case of running only once. It that
+ * case - the program is stuck until this signal is received. In other cases -
+ * it is not relevant whether or not the signal is on - since we are currently
+ * in exit flow
+ */
+ if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY &&
+ osm_exit_flag == 1 )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Signalling subnet_up_event\n" );
+ cl_event_signal( p_sm_mgr->p_state_mgr->p_subnet_up_event );
+ goto Exit;
+ }
+
+ /*
+ * Incr the retry number.
+ * If it reached the max_retry_number in the subnet opt - call
+ * osm_sm_state_mgr_process with signal OSM_SM_SIGNAL_POLLING_TIMEOUT
+ */
+ p_sm_mgr->retry_number++;
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Retry number:%d\n", p_sm_mgr->retry_number );
+
+ if( p_sm_mgr->retry_number >= p_sm_mgr->p_subn->opt.polling_retry_number )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Reached polling_retry_number value in retrys"
+ "Go to DISCOVERY state\n" );
+ osm_sm_state_mgr_process( p_sm_mgr, OSM_SM_SIGNAL_POLLING_TIMEOUT );
+ goto Exit;
+ }
+
+ /* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */
+ __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+ /* restart the timer */
+ cl_status = cl_timer_start( &p_sm_mgr->polling_timer,
+ sminfo_polling_timeout );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_polling_callback : ERROR 1000: "
+ "Failed to re-start timer\n" );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_construct(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ cl_memclr( p_sm_mgr, sizeof( *p_sm_mgr ) );
+ cl_spinlock_construct( &p_sm_mgr->state_lock );
+ cl_timer_construct( &p_sm_mgr->polling_timer );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_destroy(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_destroy );
+
+ CL_ASSERT( p_sm_mgr );
+
+ cl_spinlock_destroy( &p_sm_mgr->state_lock );
+ cl_timer_destroy( &p_sm_mgr->polling_timer );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_init(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_state_mgr_t * const p_state_mgr,
+ IN osm_subn_t * const p_subn,
+ IN osm_req_t * const p_req,
+ IN osm_log_t * const p_log )
+{
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_sm_state_mgr_init );
+
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_state_mgr );
+ CL_ASSERT( p_req );
+
+ osm_sm_state_mgr_construct( p_sm_mgr );
+
+ p_sm_mgr->p_log = p_log;
+ p_sm_mgr->p_req = p_req;
+ p_sm_mgr->p_subn = p_subn;
+ p_sm_mgr->p_state_mgr = p_state_mgr;
+
+ /* init the state of the SM to idle */
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_INIT;
+
+ status = cl_spinlock_init( &p_sm_mgr->state_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_init: ERR 3201: "
+ "Spinlock init failed (%s).\n", CL_STATUS_MSG( status ) );
+ }
+
+ status = cl_timer_init( &p_sm_mgr->polling_timer,
+ __osm_sm_state_mgr_polling_callback, p_sm_mgr );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_init: ERR 3206: "
+ "Timer init failed (%s).\n", CL_STATUS_MSG( status ) );
+ }
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_signal_error(
+ IN const osm_sm_state_mgr_t * const p_sm_mgr,
+ IN const osm_sm_signal_t signal )
+{
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_signal_error: ERR 3207: "
+ "Invalid signal %s in state %s.\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_signal_master_is_alive(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_signal_master_is_alive );
+ p_sm_mgr->retry_number = 0;
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osm_sm_state_mgr_process(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_sm_signal_t signal )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_process );
+
+ CL_ASSERT( p_sm_mgr );
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process.
+ */
+ cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_sm_state_mgr_process: "
+ "Received signal %s in state %s.\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ }
+
+ switch ( p_sm_mgr->p_subn->sm_state )
+ {
+ case IB_SMINFO_STATE_INIT:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_INIT:
+ /*
+ * Update the state of the SM to DISCOVERING
+ */
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ break;
+
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_DISCOVERING:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+ /*
+ * Update the state of the SM to MASTER
+ */
+ __osm_sm_state_mgr_master_msg( p_sm_mgr );
+ /* Turn on the moved_to_master_state flag */
+ p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+ /* Turn on the first_time_master_sweep flag */
+ if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+ p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+ /*
+ * Make sure to set the subnet master_sm_base_lid
+ * to the sm_base_lid value
+ */
+ p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+ break;
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ /*
+ * Stop the discovering
+ */
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr,
+ OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED );
+ break;
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+ /*
+ * Finished all discovery actions - move to STANDBY
+ * start the polling
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ /*
+ * Since another SM is doing the LFT config - we should not
+ * ignore the results of it
+ */
+ p_sm_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_STANDBY:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+ case OSM_SM_SIGNAL_DISCOVER:
+ /*
+ * case 1: Polling timeout occured - this means that the Master SM
+ * no longer alive.
+ * case 2: Got a signal to move to DISCOVERING
+ * Move to DISCOVERING state, and start sweeping
+ */
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+ break;
+ case OSM_SM_SIGNAL_DISABLE:
+ /*
+ * Update the state to NOT_ACTIVE
+ */
+ __osm_sm_state_mgr_notactive_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE;
+ break;
+ case OSM_SM_SIGNAL_HANDOVER:
+ /*
+ * Update state to MASTER, and start sweeping
+ * OPTIONAL: send ACKNOWLEDGE
+ */
+ __osm_sm_state_mgr_master_msg( p_sm_mgr );
+ /* Turn on the moved_to_master_state flag */
+ p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+ /* Turn on the first_time_master_sweep flag */
+ if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+ p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+ /* Turn on the force_immediate_heavy_sweep - we want a
+ * heavy sweep to occure on the first sweep of this SM. */
+ p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+ /*
+ * Make sure to set the subnet master_sm_base_lid
+ * to the sm_base_lid value
+ */
+ p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+ p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+ break;
+ case OSM_SM_SIGNAL_ACKNOWLEDGE:
+ /*
+ * Do nothing - already moved to STANDBY
+ */
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_NOTACTIVE:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_STANDBY:
+ /*
+ * Update the state to STANDBY
+ * start the polling
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_MASTER:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+ /*
+ * we received a polling timeout - this means that we waited for
+ * a remote master sm to send us a handover, but didn't get it, and
+ * didn't get a response from that remote sm.
+ * We want to force a heavy sweep - hopefully this occurred because
+ * the remote sm died, and we'll find this out and configure the
+ * subnet after a heavy sweep.
+ * We also want to clear the p_polling_sm object - since we are
+ * done polling on that remote sm - we are sweeping again.
+ */
+ case OSM_SM_SIGNAL_HANDOVER:
+ /*
+ * If we received a handover in a master state - then we want to
+ * force a heavy sweep. This means that either we are in a sweep
+ * currently - in this case - no change, or we are in idle state -
+ * since we recognized a master SM before - so we want to make a
+ * heavy sweep and reconfigure the new subnet.
+ * We also want to clear the p_polling_sm object - since we are
+ * done polling on that remote sm - we got a handover from it.
+ */
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_state_mgr_process: "
+ "Forcing immediate heavy sweep. "
+ "Received OSM_SM_SIGNAL_HANDOVER \n" );
+ p_sm_mgr->p_polling_sm = NULL;
+ p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_SWEEP );
+ break;
+ case OSM_SM_SIGNAL_HANDOVER_SENT:
+ /*
+ * Just sent a HANDOVER signal - move to STANDBY
+ * start the polling
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ case OSM_SM_SIGNAL_WAIT_FOR_HANDOVER:
+ /*
+ * We found a remote master SM, and we are waiting for it
+ * to handover the mastership to us. Need to start polling
+ * on that SM, to make sure it is alive, if it isn't - then
+ * we should move back to discovering, since something must
+ * have happend to it.
+ */
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ case OSM_SM_SIGNAL_DISCOVER:
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ default:
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_process: ERR 3208: "
+ "Invalid state %s.\n",
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+
+ }
+
+ cl_spinlock_release( &p_sm_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osm_sm_state_mgr_check_legality(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_sm_signal_t signal )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_check_legality );
+
+ CL_ASSERT( p_sm_mgr );
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process.
+ */
+ cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_sm_state_mgr_check_legality: "
+ "Received signal %s in state %s.\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ }
+
+ switch ( p_sm_mgr->p_subn->sm_state )
+ {
+ case IB_SMINFO_STATE_INIT:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_INIT:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_DISCOVERING:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_STANDBY:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+ case OSM_SM_SIGNAL_DISCOVER:
+ case OSM_SM_SIGNAL_DISABLE:
+ case OSM_SM_SIGNAL_HANDOVER:
+ case OSM_SM_SIGNAL_ACKNOWLEDGE:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_NOTACTIVE:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_STANDBY:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_MASTER:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_HANDOVER:
+ case OSM_SM_SIGNAL_HANDOVER_SENT:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ default:
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_check_legality: ERR 3209: "
+ "Invalid state %s.\n",
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ status = IB_INVALID_PARAMETER;
+
+ }
+
+ cl_spinlock_release( &p_sm_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_construct(
+ IN osm_sminfo_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_destroy(
+ IN osm_sminfo_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_init(
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN osm_sm_state_mgr_t* const p_sm_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_sminfo_rcv_init );
+
+ osm_sminfo_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_state_mgr = p_state_mgr;
+ p_rcv->p_sm_state_mgr = p_sm_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ Return TRUE if the remote sm given (by ib_sm_info_t) is higher,
+ return FALSE otherwise.
+ By higher - we mean: SM with higher priority or with same priority
+ and lower GUID.
+**********************************************************************/
+inline boolean_t
+__osm_sminfo_rcv_remote_sm_is_higher (
+ IN const osm_sminfo_rcv_t* p_rcv,
+ IN const ib_sm_info_t* p_remote_sm )
+{
+
+ return( osm_sm_is_greater_than( ib_sminfo_get_priority( p_remote_sm ),
+ p_remote_sm->guid,
+ p_rcv->p_subn->opt.sm_priority,
+ p_rcv->p_subn->sm_port_guid) );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_process_get_request(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_smp_t* p_smp;
+ ib_sm_info_t* p_smi = (ib_sm_info_t*)payload;
+ ib_api_status_t status;
+ ib_sm_info_t* p_remote_smi;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_request );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ No real need to grab the lock for this function.
+ */
+ cl_memclr( payload, sizeof( payload ) );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->method == IB_MAD_METHOD_GET );
+
+ p_smi->guid = p_rcv->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+ p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+ p_rcv->p_subn->opt.sm_priority << 4);
+ /*
+ p.750 row 11 - Return 0 for the SM key unless we authenticate the
+ requestor as the master SM.
+ */
+ p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) );
+ if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_get_request: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requestor is not authenticated as master - set sm_key to zero. */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_get_request: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_request: ERR 2F02: "
+ "Error sending response (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * Check if the p_smp received is legal.
+ * Current checks:
+ * MADHeader:AttributeModifiers of ACKNOWLEDGE that was not sent by a
+ * Standby SM.
+ * MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER
+ * that was not sent by a Master SM.
+ * FUTURE - TO DO:
+ * Check that the SM_Key is matching.
+ **********************************************************************/
+ib_api_status_t
+__osm_sminfo_rcv_check_set_req_legality(
+ IN const ib_smp_t* const p_smp )
+{
+ ib_sm_info_t* p_smi;
+
+ p_smi = ib_smp_get_payload_ptr( p_smp );
+
+ if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE)
+ {
+ if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_STANDBY )
+ {
+ return( IB_SUCCESS );
+ }
+ }
+ else if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER ||
+ p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE ||
+ p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY ||
+ p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER )
+ {
+ if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ return( IB_SUCCESS );
+ }
+ }
+
+ return( IB_INVALID_PARAMETER );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_process_set_request(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_smp_t* p_smp;
+ ib_sm_info_t* p_smi = (ib_sm_info_t*)payload;
+ ib_sm_info_t* p_rcv_smi;
+ ib_api_status_t status;
+ osm_sm_signal_t sm_signal;
+ ib_sm_info_t* p_remote_smi;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_request );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ No real need to grab the lock for this function.
+ */
+ cl_memclr( payload, sizeof( payload ) );
+
+ /* get the lock */
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_rcv_smi = ib_smp_get_payload_ptr( p_smp );
+
+ if( p_smp->method != IB_MAD_METHOD_SET )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F03: "
+ "Unsupported method 0x%X.\n",
+ p_smp->method );
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ p_smi->guid = p_rcv->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+ p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+ p_rcv->p_subn->opt.sm_priority << 4);
+ /*
+ p.750 row 11 - Return 0 for the SM key unless we authenticate the
+ requestor as the master SM.
+ */
+ p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) );
+ if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requestor is not authenticated as master - set sm_key to zero. */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ /* Check the legality of the packet */
+ status = __osm_sminfo_rcv_check_set_req_legality( p_smp );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F04: "
+ "Check legality failed. AttributeModifier:0x%X RemoteState:%s\n",
+ p_smp->attr_mod,
+ osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) );
+ /* send a response with error code */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F05: "
+ "Error sending response (%s).\n",
+ ib_get_err_str( status ) );
+ }
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ /* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */
+ switch (p_smp->attr_mod)
+ {
+ case IB_SMINFO_ATTR_MOD_HANDOVER:
+ sm_signal = OSM_SM_SIGNAL_HANDOVER;
+ break;
+ case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE:
+ sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE;
+ break;
+ case IB_SMINFO_ATTR_MOD_DISABLE:
+ sm_signal = OSM_SM_SIGNAL_DISABLE;
+ break;
+ case IB_SMINFO_ATTR_MOD_STANDBY:
+ sm_signal = OSM_SM_SIGNAL_STANDBY;
+ break;
+ case IB_SMINFO_ATTR_MOD_DISCOVER:
+ sm_signal = OSM_SM_SIGNAL_DISCOVER;
+ break;
+ default:
+ /*
+ This code shouldn't be reached - checked in the
+ check legality
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F06: "
+ "THIS CODE SHOULD NOT BE REACHED!! \n");
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ /* check legality of the needed transition in the SM state machine */
+ status = osm_sm_state_mgr_check_legality( p_rcv->p_sm_state_mgr,
+ sm_signal );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F07: "
+ "Check legality of SM needed transition. AttributeModifier:0x%X RemoteState:%s\n",
+ p_smp->attr_mod,
+ osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) );
+ /* send a response with error code */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F08: "
+ "Error sending response (%s).\n",
+ ib_get_err_str( status ) );
+ }
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ /* the SubnSet (SMInfo) command is ok. Send a response. */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F09: "
+ "Error sending response (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ /* it is a legal packet - act according to it */
+
+ /* if the AttributeModifier is STANDBY - need to save on the */
+ /* p_sm_state_mgr in the maseter_guid variable - the guid of the */
+ /* current master. */
+ if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Received a STANDBY signalUpdating "
+ "sm_state_mgr master_guid: 0x%X.\n",
+ p_rcv_smi->guid );
+ p_rcv->p_sm_state_mgr->master_guid = p_rcv_smi->guid;
+ }
+
+ /* call osm_sm_state_mgr_process with the received signal. */
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ status = osm_sm_state_mgr_process( p_rcv->p_sm_state_mgr,
+ sm_signal);
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F10: "
+ "Error in SM state transition (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ * Return a signal with which to call the osm_state_mgr_process.
+ * This is done since we are locked by p_rcv->p_lock in this function,
+ * and thus cannot call osm_state_mgr_process (that locks the state_lock).
+ * If return OSM_SIGNAL_NONE - do not call osm_state_mgr_process.
+ **********************************************************************/
+osm_signal_t
+__osm_sminfo_rcv_process_get_sm(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_remote_sm_t* const p_sm )
+{
+ const ib_sm_info_t* p_smi;
+ osm_signal_t ret_val = OSM_SIGNAL_NONE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_sm );
+
+ p_smi = &p_sm->smi;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Detected SM 0x%016" PRIx64 " in state %u.\n",
+ cl_ntoh64( p_smi->guid ), ib_sminfo_get_state( p_smi ) );
+ }
+
+ /*
+ Check the state of this SM vs. our own.
+ */
+ switch( p_rcv->p_subn->sm_state )
+ {
+ case IB_SMINFO_STATE_NOTACTIVE:
+ break;
+
+ case IB_SMINFO_STATE_DISCOVERING:
+ switch( ib_sminfo_get_state( p_smi ) )
+ {
+ case IB_SMINFO_STATE_NOTACTIVE:
+ break;
+ case IB_SMINFO_STATE_MASTER:
+ ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+ /* save on the p_sm_state_mgr the guid of the current master. */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Found master SM. Updating sm_state_mgr master_guid: 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_sm->p_port->guid ) );
+ p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid;
+ break;
+ case IB_SMINFO_STATE_DISCOVERING:
+ case IB_SMINFO_STATE_STANDBY:
+ if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+ {
+ /* the remote is a higher sm - need to stop sweeping */
+ ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+ /* save on the p_sm_state_mgr the guid of the higher SM we found - */
+ /* we will poll it - as long as it lives - we should be in Standby. */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Found higher SM. Updating sm_state_mgr master_guid: 0x%X.\n",
+ p_sm->p_port->guid );
+ p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_STANDBY:
+ /* if the guid of the SM that sent us this response is equal to the */
+ /* p_sm_mgr->master_guid - then this is a signal that the polling */
+ /* */
+ switch( ib_sminfo_get_state( p_smi ) )
+ {
+ case IB_SMINFO_STATE_MASTER:
+ /* This means the master is alive */
+ /* Signal that to the SM state mgr */
+ osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+ break;
+ case IB_SMINFO_STATE_STANDBY:
+ /* This should be the response from the sm we are polling. */
+ /* If it is - then signal master is alive */
+ if (p_rcv->p_sm_state_mgr->master_guid == p_sm->p_port->guid)
+ {
+ /* Make sure that it is an SM with higher priority than us.
+ If we started polling it when it was master, and it moved
+ to standby - then it might be with a lower priority than
+ us - and then we don't want to continue polling it. */
+ if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+ osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+ }
+ break;
+ default:
+ /* any other state - do nothing */
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_MASTER:
+ switch( ib_sminfo_get_state( p_smi ) )
+ {
+ case IB_SMINFO_STATE_MASTER:
+ /* If this is a response due to our polling, this means that we are
+ waiting for a handover from this SM, and it is still alive -
+ signal that. */
+ if ( p_rcv->p_sm_state_mgr->p_polling_sm != NULL )
+ {
+ osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+ }
+ else
+ {
+ /* This is a response we got while sweeping the subnet.
+ We will handle a case of handover needed later on, when the sweep
+ is done and all SMs are recongnized. */
+ }
+ break;
+ default:
+ /* any other state - do nothing */
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return ret_val;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_process_get_response(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_smp_t* p_smp;
+ const ib_sm_info_t* p_smi;
+ cl_qmap_t* p_sm_tbl;
+ cl_qmap_t* p_port_tbl;
+ osm_port_t* p_port;
+ ib_net64_t port_guid;
+ osm_remote_sm_t* p_sm;
+ ib_api_status_t status;
+ osm_signal_t process_get_sm_ret_val = OSM_SIGNAL_NONE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_response );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F11: "
+ "Unsupported method 0x%X.\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ p_smi = ib_smp_get_payload_ptr( p_smp );
+ p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
+ p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+ port_guid = p_smi->guid;
+
+ osm_dump_sm_info( p_rcv->p_log, p_smi, OSM_LOG_DEBUG );
+
+ /*
+ Check that the sm_key of the found SM is the same as ours,
+ or is zero. If not - OpenSM cannot continue with configuration!. */
+ if ( p_smi->sm_key != 0 &&
+ p_smi->sm_key != p_rcv->p_subn->opt.sm_key )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F18: "
+ "Got SM with sm_key that doesn't match our "
+ "local key. Exiting.\n" );
+ osm_log( p_rcv->p_log, OSM_LOG_SYS,
+ "Found remote SM with non-matching sm_key. Exiting\n" );
+ osm_exit_flag = TRUE;
+ goto Exit;
+ }
+
+ /*
+ Determine if we already have an Other SM object for this SM.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F12: "
+ "No Port object for this SM.\n" );
+ goto Exit;
+ }
+
+ if( osm_port_get_guid( p_port ) != p_smi->guid )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F13: "
+ "Bogus SM port GUID."
+ "\n\t\t\t\tExpected 0x%016" PRIx64
+ ", Received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ cl_ntoh64( p_smi->guid ) );
+ goto Exit;
+ }
+
+ p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid );
+ if( p_sm == (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) )
+ {
+ p_sm = cl_malloc( sizeof(*p_sm) );
+ if( p_sm == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F14: "
+ "Unable to allocate SM object.\n" );
+ goto Exit;
+ }
+
+ status = osm_remote_sm_init( p_sm, p_port, p_smi );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F15: "
+ "Other SM object initialization failed (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ cl_qmap_insert( p_sm_tbl, port_guid, &p_sm->map_item );
+ }
+ else
+ {
+ /*
+ We already know this SM.
+ Update the SMInfo attribute.
+ */
+ p_sm->smi = *p_smi;
+ }
+
+ process_get_sm_ret_val = __osm_sminfo_rcv_process_get_sm( p_rcv, p_sm );
+
+ Exit:
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /* If process_get_sm_ret_val != OSM_SIGNAL_NONE then we have to signal
+ * to the state_mgr with that signal. */
+ if (process_get_sm_ret_val != OSM_SIGNAL_NONE)
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ process_get_sm_ret_val );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_process_set_response(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_smp_t* p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_response );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_response: ERR 2F16: "
+ "Unsupported method 0x%X.\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ /* Check the AttributeModifier */
+ if ( p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_response: ERR 2F17: "
+ "Unsupported attribute modifier 0x%X.\n",
+ p_smp->attr_mod );
+ goto Exit;
+ }
+
+ /*
+ This is a response on a HANDOVER request -
+ Nothing to do.
+ */
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_process(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ ib_smp_t *p_smp;
+ osm_smi_context_t *p_smi_context;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ Determine if this is a request for our own SMInfo
+ or if this is a response to our request for another
+ SM's SMInfo.
+ */
+ if( ib_smp_is_response( p_smp ) )
+ {
+ /* Get the context - to see if this is a response to a Get or Set method */
+ p_smi_context = osm_madw_get_smi_context_ptr( p_madw );
+ if ( p_smi_context->set_method == FALSE )
+ {
+ /* this is a response to a Get method */
+ __osm_sminfo_rcv_process_get_response( p_rcv, p_madw );
+ }
+ else
+ {
+ /* this is a response to a Set method */
+ __osm_sminfo_rcv_process_set_response( p_rcv, p_madw );
+ }
+ }
+ else
+ {
+ /* This is a request */
+ if ( p_smp->method == IB_MAD_METHOD_GET )
+ {
+ /* This is a SubnGet request */
+ __osm_sminfo_rcv_process_get_request( p_rcv, p_madw );
+ }
+ else
+ {
+ /* This is a SubnSet request */
+ __osm_sminfo_rcv_process_set_request( p_rcv, p_madw );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sminfo_rcv_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_sminfo_rcv_process( ((osm_sminfo_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_construct(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_destroy(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sminfo_rcv_ctrl_init );
+
+ osm_sminfo_rcv_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SM_INFO,
+ __osm_sminfo_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sminfo_rcv_ctrl_init: ERR 3001: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_t.
+ * This file implements the Discovery Done Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_construct(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof( *p_mgr ) );
+ cl_spinlock_construct( &p_mgr->state_lock );
+ cl_spinlock_construct( &p_mgr->idle_lock );
+ p_mgr->state = OSM_SM_STATE_INIT;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_destroy(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_destroy );
+
+ CL_ASSERT( p_mgr );
+
+ /* destroy the locks */
+ cl_spinlock_destroy( &p_mgr->state_lock );
+ cl_spinlock_destroy( &p_mgr->idle_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_init(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_subn_t * const p_subn,
+ IN osm_lid_mgr_t * const p_lid_mgr,
+ IN osm_ucast_mgr_t * const p_ucast_mgr,
+ IN osm_mcast_mgr_t * const p_mcast_mgr,
+ IN osm_link_mgr_t * const p_link_mgr,
+ IN osm_drop_mgr_t * const p_drop_mgr,
+ IN osm_req_t * const p_req,
+ IN osm_stats_t * const p_stats,
+ IN osm_sm_state_mgr_t * const p_sm_state_mgr,
+ IN const osm_sm_mad_ctrl_t * const p_mad_ctrl,
+ IN cl_plock_t * const p_lock,
+ IN cl_event_t * const p_subnet_up_event,
+ IN char *const p_report_buf,
+ IN osm_log_t * const p_log )
+{
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_state_mgr_init );
+
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lid_mgr );
+ CL_ASSERT( p_ucast_mgr );
+ CL_ASSERT( p_mcast_mgr );
+ CL_ASSERT( p_link_mgr );
+ CL_ASSERT( p_drop_mgr );
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_stats );
+ CL_ASSERT( p_sm_state_mgr );
+ CL_ASSERT( p_mad_ctrl );
+ CL_ASSERT( p_lock );
+ CL_ASSERT( p_report_buf );
+
+ osm_state_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lid_mgr = p_lid_mgr;
+ p_mgr->p_ucast_mgr = p_ucast_mgr;
+ p_mgr->p_mcast_mgr = p_mcast_mgr;
+ p_mgr->p_link_mgr = p_link_mgr;
+ p_mgr->p_drop_mgr = p_drop_mgr;
+ p_mgr->p_mad_ctrl = p_mad_ctrl;
+ p_mgr->p_req = p_req;
+ p_mgr->p_stats = p_stats;
+ p_mgr->p_sm_state_mgr = p_sm_state_mgr;
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_subnet_up_event = p_subnet_up_event;
+ p_mgr->p_report_buf = p_report_buf;
+ p_mgr->state_step_mode = OSM_STATE_STEP_CONTINUOUS;
+ p_mgr->next_stage_signal = OSM_SIGNAL_NONE;
+
+ status = cl_spinlock_init( &p_mgr->state_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_init: ERR 3301: "
+ "Spinlock init failed (%s).\n", CL_STATUS_MSG( status ) );
+ }
+
+ cl_qlist_init( &p_mgr->idle_time_list );
+
+ status = cl_spinlock_init( &p_mgr->idle_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_init: ERR 3302: "
+ "Spinlock init failed (%s).\n", CL_STATUS_MSG( status ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_up_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ /*
+ * This message should be written only once - when the
+ * SM moves to Master state and the subnet is up for
+ * the first time. The change of state is marked with
+ * the subnet flag moved_to_master_state
+ */
+ if( p_mgr->p_subn->moved_to_master_state == TRUE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "SUBNET UP\n" ); /* Format Waived */
+ /* clear the signal */
+ p_mgr->p_subn->moved_to_master_state = FALSE;
+ }
+
+ if( p_mgr->p_subn->opt.sweep_interval )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_up_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "**************************** SUBNET UP "
+ "***************************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_up_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************* SUBNET UP "
+ "(sweep disabled) *******************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_init_errors_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "Errors during initialization.\n" ); /* Format Waived */
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_init_errors_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "****************** ERRORS DURING INITI"
+ "ALIZATION ******************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_light_sweep_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_light_sweep_done_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "********************** LIGHT SWEEP "
+ "COMPLETE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_standby_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_standby_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING STANDBY"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sm_port_down_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "SM port is down.\n" ); /* Format Waived */
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sm_port_down_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "************************** SM PORT DOWN "
+ "**************************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_lid_assign_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_lid_assign_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "***** LID ASSIGNMENT COMPLETE - STARTING SWITC"
+ "H TABLE CONFIG *****\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_set_sm_lid_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_set_sm_lid_done_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "**** SM LID ASSIGNMENT COMPLETE - STARTING SUBN"
+ "ET LID CONFIG *****\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_switch_config_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_switch_config_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "***************** SWITCHES CONFIGURED FOR UNICAST "
+ "****************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_multicast_config_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_multicast_config_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "**************** SWITCHES CONFIGURED FOR MULTICAST "
+ "***************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_ports_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_links_ports_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******* LINKS PORTS CONFIGURED - SET LINKS TO ARMED "
+ "STATE ********\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_armed_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_links_armed_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "************* LINKS ARMED - SET LINKS TO ACTIVE "
+ "STATE ************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_heavy_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******************** INITIATING HEAVY SWEEP "
+ "**********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_heavy_done_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "********************* HEAVY SWEEP COMPLETE "
+ "***********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_light_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_light_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******************** INITIATING LIGHT SWEEP "
+ "**********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_state_mgr_signal_warning(
+ IN const osm_state_mgr_t * const p_mgr,
+ IN const osm_signal_t signal )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_signal_warning: "
+ "Invalid signal %s(%d) in state %s.\n",
+ osm_get_sm_signal_str( signal ),
+ signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_state_mgr_signal_error(
+ IN const osm_state_mgr_t * const p_mgr,
+ IN const osm_signal_t signal )
+{
+ /* the Request for IDLE processing can come async to the state so it
+ * really just a verbose ... */
+ if( signal == OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST )
+ __osm_state_mgr_signal_warning( p_mgr, signal );
+ else
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_signal_error: ERR 3303: "
+ "Invalid signal %s(%d) in state %s.\n",
+ osm_get_sm_signal_str( signal ),
+ signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_node_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_node_t *p_node = ( osm_node_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_node_count: "
+ "Resetting discovery count for node 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ osm_node_discovery_count_reset( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_port_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_port_t *p_port = ( osm_port_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_port_count: "
+ "Resetting discovery count for port 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ }
+
+ osm_port_discovery_count_reset( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_switch_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_switch_t *p_sw = ( osm_switch_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_switch_count: "
+ "Resetting discovery count for switch 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ) );
+ }
+
+ osm_switch_discovery_count_reset( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_get_sw_info(
+ IN cl_map_item_t * const p_object,
+ IN void *context )
+{
+ osm_node_t *p_node;
+ osm_dr_path_t *p_dr_path;
+ osm_madw_context_t mad_context;
+ osm_switch_t *const p_sw = ( osm_switch_t * ) p_object;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_sw_info );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_dr_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ mad_context.si_context.node_guid = osm_node_get_node_guid( p_node );
+ mad_context.si_context.set_method = FALSE;
+ mad_context.si_context.light_sweep = TRUE;
+
+ status = osm_req_get( p_mgr->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0, OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_get_sw_info: ERR 3304: "
+ "Request SwitchInfo failed.\n" );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Initiate a remote port info request for the given physical port
+ **********************************************************************/
+static void
+__osm_state_mgr_get_remote_port_info(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_physp_t * const p_physp )
+{
+ osm_dr_path_t *p_dr_path;
+ osm_dr_path_t rem_node_dr_path;
+ osm_madw_context_t mad_context;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_remote_port_info );
+
+ /* generate a dr path leaving on the physp to the remote node */
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ cl_memcpy( &rem_node_dr_path, p_dr_path, sizeof( osm_dr_path_t ) );
+ osm_dr_path_extend( &rem_node_dr_path, osm_physp_get_port_num( p_physp ) );
+
+ cl_memclr( &mad_context, sizeof( mad_context ) );
+
+ mad_context.pi_context.node_guid =
+ osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) );
+ mad_context.pi_context.port_guid =
+ cl_hton64( osm_physp_get_port_num( p_physp ) );
+ mad_context.pi_context.set_method = FALSE;
+ mad_context.pi_context.light_sweep = TRUE;
+ mad_context.pi_context.ignore_errors = FALSE;
+ mad_context.pi_context.update_master_sm_base_lid = FALSE;
+
+ /* note that with some negative logic - if the query failed it means that
+ * there is no point in going to heavy sweep */
+ status = osm_req_get( p_mgr->p_req,
+ &rem_node_dr_path,
+ IB_MAD_ATTR_PORT_INFO,
+ 0, CL_DISP_MSGID_NONE, &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_get_remote_port_info: ERR 332E: "
+ "Request PortInfo failed.\n" );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Initiates a thorough sweep of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_sweep_hop_0(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status;
+ osm_dr_path_t dr_path;
+ osm_bind_handle_t h_bind;
+ osm_ni_context_t ni_context;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_0 );
+
+ cl_memclr( path_array, sizeof( path_array ) );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ __osm_state_mgr_sweep_heavy_msg( p_mgr );
+
+ /*
+ * Start the sweep by clearning the port counts, then
+ * get our own NodeInfo at 0 hops.
+ */
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->node_guid_tbl,
+ __osm_state_mgr_reset_node_count, p_mgr );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->port_guid_tbl,
+ __osm_state_mgr_reset_port_count, p_mgr );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->sw_guid_tbl,
+ __osm_state_mgr_reset_switch_count, p_mgr );
+
+ /* Set the in_sweep_hop_0 flag in subn to be TRUE.
+ * This will indicate the sweeping not to continue beyond the
+ * the current node.
+ * This is relevant for the case of SM on switch, since in the
+ * switch info we need to signal somehow not to continue
+ * the sweeping. */
+ p_mgr->p_subn->in_sweep_hop_0 = TRUE;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ cl_memclr( &ni_context, sizeof( ni_context ) );
+ osm_dr_path_init( &dr_path, h_bind, 0, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &dr_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, NULL );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_0: ERR 3305: "
+ "Request NodeInfo failed.\n" );
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_sweep_hop_0: "
+ "No bound ports. Deferring sweep...\n" );
+ status = IB_INVALID_STATE;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ Clear out all existing port lid assignments
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_clean_known_lids(
+ IN osm_state_mgr_t * const p_mgr )
+{
+
+ ib_api_status_t status = IB_SUCCESS;
+ cl_ptr_vector_t *p_vec = &( p_mgr->p_subn->port_lid_tbl );
+ uint32_t i;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_clean_known_lids );
+
+ /* we need a lock here! */
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+ for( i = 0; i < cl_ptr_vector_get_size( p_vec ); i++ )
+ cl_ptr_vector_set( p_vec, i, NULL );
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+
+}
+
+/**********************************************************************
+ Notifies the transport layer that the local LID has changed,
+ which give it a chance to update address vectors, etc..
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_notify_lid_change(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status;
+ osm_bind_handle_t h_bind;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_notify_lid_change );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_notify_lid_change: ERR 3306: "
+ "No bound ports.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Notify the transport layer that we changed the local LID.
+ */
+ status = osm_vendor_local_lid_change( h_bind );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_notify_lid_change: ERR 3307: "
+ "Vendor LID update failed (%s).\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ Returns true if the SM port is down.
+ The SM's port object must exist in the port_guid table.
+**********************************************************************/
+static boolean_t
+__osm_state_mgr_is_sm_port_down(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_net64_t port_guid;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ cl_qmap_t *p_tbl;
+ uint8_t state;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_is_sm_port_down );
+
+ port_guid = p_mgr->p_subn->sm_port_guid;
+
+ /*
+ * If we don't know our own port guid yet, assume the port is down.
+ */
+ if( port_guid == 0 )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_is_sm_port_down: ERR 3308: "
+ "SM port GUID unknown.\n" );
+ state = IB_LINK_DOWN;
+ goto Exit;
+ }
+
+ p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ CL_ASSERT( port_guid );
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_get( p_tbl, port_guid );
+ if( p_port == ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_is_sm_port_down: ERR 3309: "
+ "SM port with GUID:%016" PRIx64 " is unknown.\n",
+ cl_ntoh64( port_guid ) );
+ state = IB_LINK_DOWN;
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ state = osm_physp_get_port_state( p_physp );
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( state == IB_LINK_DOWN );
+}
+
+/**********************************************************************
+ Sweeps the node 1 hop away.
+ This sets off a "chain reaction" that causes discovery of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_sweep_hop_1(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_bind_handle_t h_bind;
+ osm_madw_context_t context;
+ osm_node_t *p_node;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_dr_path_t *p_dr_path;
+ osm_dr_path_t hop_1_path;
+ ib_net64_t port_guid;
+ uint8_t port_num;
+ cl_qmap_t *p_port_tbl;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+ uint8_t num_ports;
+ osm_physp_t *p_ext_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_1 );
+
+ /*
+ * First, get our own port and node objects.
+ */
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ port_guid = p_mgr->p_subn->sm_port_guid;
+
+ CL_ASSERT( port_guid );
+
+ /* Set the in_sweep_hop_0 flag in subn to be FALSE.
+ * This will indicate the sweeping to continue beyond the
+ * the current node.
+ * This is relevant for the case of SM on switch, since in the
+ * switch info we need to signal that the sweeping should
+ * continue through the switch. */
+ p_mgr->p_subn->in_sweep_hop_0 = FALSE;
+
+ p_port = ( osm_port_t * ) cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == ( osm_port_t * ) cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3310: "
+ "No SM port object.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ port_num = ib_node_info_get_local_port_num( &p_node->node_info );
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_sweep_hop_1: "
+ "Probing hop 1 on local port %u.\n", port_num );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+
+ CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+
+ cl_memclr( path_array, sizeof( path_array ) );
+ /* the hop_1 operations depend on the type of our node.
+ * Currently - legal nodes that can host SM are SW and CA */
+ switch ( osm_node_get_type( p_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ context.ni_context.node_guid = osm_node_get_node_guid( p_node );
+ context.ni_context.port_num = port_num;
+
+ path_array[1] = port_num;
+
+ osm_dr_path_init( &hop_1_path, h_bind, 1, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &hop_1_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3311: "
+ "Request NodeInfo failed.\n" );
+ }
+ break;
+
+ case IB_NODE_TYPE_SWITCH:
+ /* Need to go over all the ports of the switch, and send a node_info
+ * from them. This doesn't include the port 0 of the switch, which
+ * hosts the SM.
+ * Note: We'll send another switchInfo on port 0, since if no ports
+ * are connected, we still want to get some response, and have the
+ * subnet come up.
+ */
+ num_ports = osm_node_get_num_physp( p_node );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ /* go through the port only if the port is not DOWN */
+ p_ext_physp = osm_node_get_physp_ptr( p_node, port_num );
+ /* Make sure the physp object exists */
+ if( !p_ext_physp )
+ continue;
+ if( ib_port_info_get_port_state( &( p_ext_physp->port_info ) ) >
+ IB_LINK_DOWN )
+ {
+ context.ni_context.node_guid = osm_node_get_node_guid( p_node );
+ context.ni_context.port_num = port_num;
+
+ path_array[1] = port_num;
+
+ osm_dr_path_init( &hop_1_path, h_bind, 1, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &hop_1_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3312: "
+ "Request NodeInfo failed.\n" );
+ }
+ }
+ }
+ break;
+
+ default:
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3313: "
+ " Supported node type that hosts SM is CA or SW only" );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ Initiates a light-weight sweep of the subnet.
+ Used during normal sweeps after the subnet is up.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_light_sweep_start(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_bind_handle_t h_bind;
+ cl_qmap_t *p_sw_tbl;
+ cl_list_t *p_no_rem_port_list;
+ cl_list_iterator_t list_iter;
+
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_light_sweep_start );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ cl_memclr( path_array, sizeof( path_array ) );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ __osm_state_mgr_sweep_light_msg( p_mgr );
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ cl_qmap_apply_func( p_sw_tbl, __osm_state_mgr_get_sw_info, p_mgr );
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ /* now scan the list of physical ports that were not down but have no remote port */
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_no_rem_port_list = &p_mgr->p_subn->light_sweep_physp_list;
+ list_iter = cl_list_head( p_no_rem_port_list );
+ while( list_iter != cl_list_end( p_no_rem_port_list ) )
+ {
+ __osm_state_mgr_get_remote_port_info( p_mgr,
+ ( osm_physp_t * )
+ cl_list_obj( list_iter ) );
+ list_iter = cl_list_next( list_iter );
+ }
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_light_sweep_start: "
+ "No bound ports. Deferring sweep...\n" );
+ status = IB_INVALID_STATE;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_topology_file_create(
+ IN osm_state_mgr_t * const p_mgr )
+{
+
+ const osm_node_t *p_node;
+ char *file_name;
+ FILE *rc;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_topology_file_create );
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+ file_name =
+ ( char * )cl_malloc( strlen( p_mgr->p_subn->opt.dump_files_dir ) + 12 );
+
+ CL_ASSERT( file_name );
+
+ strcpy( file_name, p_mgr->p_subn->opt.dump_files_dir );
+ strcat( file_name, "/subnet.lst" );
+
+ if( ( rc = fopen( file_name, "w" ) ) == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_topology_file_create: "
+ "fopen failed for file:%s\n", file_name );
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ goto Exit;
+ }
+
+ p_node = ( osm_node_t * ) cl_qmap_head( &p_mgr->p_subn->node_guid_tbl );
+ while( p_node !=
+ ( osm_node_t * ) cl_qmap_end( &p_mgr->p_subn->node_guid_tbl ) )
+ {
+ if( p_node->node_info.num_ports )
+ {
+ uint32_t cPort;
+ osm_node_t *p_nbnode;
+ osm_physp_t *p_physp;
+ osm_physp_t *p_default_physp;
+ osm_physp_t *p_rphysp;
+ uint8_t link_speed_act;
+
+ for( cPort = 1; cPort < osm_node_get_num_physp( p_node ); cPort++ )
+ {
+ uint8_t port_state;
+
+ p_physp = osm_node_get_physp_ptr( p_node, cPort );
+
+ if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+ continue;
+
+ p_rphysp = p_physp->p_remote_physp;
+
+ if( ( p_rphysp == NULL ) || ( !osm_physp_is_valid( p_rphysp ) ) )
+ continue;
+
+ CL_ASSERT( cPort == p_physp->port_num );
+
+ if( p_node->node_info.node_type == IB_NODE_TYPE_SWITCH )
+ {
+
+ p_default_physp = osm_node_get_physp_ptr( p_node, 0 );
+ }
+ else
+ {
+ p_default_physp = p_physp;
+ }
+
+ fprintf( rc, "{ %s%s Ports:%02X"
+ " SystemGUID:%016" PRIx64
+ " NodeGUID:%016" PRIx64
+ " PortGUID:%016" PRIx64
+ " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+ ( p_node->node_info.node_type ==
+ IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_node->node_info.
+ node_type ==
+ IB_NODE_TYPE_CA ) ?
+ "CA" : ( p_node->node_info.node_type ==
+ IB_NODE_TYPE_ROUTER ) ? "Rt" : "**",
+ ( p_default_physp->port_info.base_lid ==
+ p_default_physp->port_info.
+ master_sm_base_lid ) ? "-SM" : "",
+ p_node->node_info.num_ports,
+ cl_ntoh64( p_node->node_info.sys_guid ),
+ cl_ntoh64( p_node->node_info.node_guid ),
+ cl_ntoh64( p_physp->port_guid ),
+ cl_ntoh32( ib_node_info_get_vendor_id
+ ( &p_node->node_info ) ),
+ cl_ntoh32( p_node->node_info.device_id ),
+ cl_ntoh32( p_node->node_info.revision ),
+ p_node->node_desc.description,
+ cl_ntoh16( p_default_physp->port_info.base_lid ),
+ cPort );
+
+ p_nbnode = p_rphysp->p_node;
+
+ if( p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH )
+ {
+
+ p_default_physp = osm_node_get_physp_ptr( p_nbnode, 0 );
+ }
+ else
+ {
+ p_default_physp = p_rphysp;
+ }
+
+
+ fprintf( rc, "{ %s%s Ports:%02X"
+ " SystemGUID:%016" PRIx64
+ " NodeGUID:%016" PRIx64
+ " PortGUID:%016" PRIx64
+ " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+ ( p_nbnode->node_info.node_type ==
+ IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_nbnode->node_info.
+ node_type ==
+ IB_NODE_TYPE_CA ) ?
+ "CA" : ( p_nbnode->node_info.node_type ==
+ IB_NODE_TYPE_ROUTER ) ? "Rt" : "**",
+ ( p_default_physp->port_info.base_lid ==
+ p_default_physp->port_info.
+ master_sm_base_lid ) ? "-SM" : "",
+ p_nbnode->node_info.num_ports,
+ cl_ntoh64( p_nbnode->node_info.sys_guid ),
+ cl_ntoh64( p_nbnode->node_info.node_guid ),
+ cl_ntoh64( p_rphysp->port_guid ),
+ cl_ntoh32( ib_node_info_get_vendor_id
+ ( &p_nbnode->node_info ) ),
+ cl_ntoh32( p_nbnode->node_info.device_id ),
+ cl_ntoh32( p_nbnode->node_info.revision ),
+ p_nbnode->node_desc.description,
+ cl_ntoh16( p_default_physp->port_info.base_lid ),
+ p_rphysp->port_num );
+
+ port_state = ib_port_info_get_port_state( &p_physp->port_info );
+ link_speed_act =
+ ib_port_info_get_link_speed_active( &p_physp->port_info );
+
+ fprintf( rc, "PHY=%s LOG=%s SPD=%s\n",
+ ( p_physp->port_info.link_width_active == 1 ) ? "1x" :
+ ( p_physp->port_info.link_width_active == 2 ) ? "4x" :
+ ( p_physp->port_info.link_width_active == 8 ) ? "12x" :
+ "??",
+ ( ( port_state == IB_LINK_ACTIVE ) ? "ACT" :
+ ( port_state == IB_LINK_ARMED ) ? "ARM" :
+ ( port_state == IB_LINK_INIT ) ? "INI" : "DWN" ),
+ ( link_speed_act == 1 ) ? "2.5" :
+ ( link_speed_act == 2 ) ? "5" :
+ ( link_speed_act == 4 ) ? "10" : "??" );
+ }
+ }
+ p_node = ( osm_node_t * ) cl_qmap_next( &p_node->map_item );
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ fclose( rc );
+
+ Exit:
+ cl_free( file_name );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__osm_state_mgr_report(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ const cl_qmap_t *p_tbl;
+ const osm_port_t *p_port;
+ const osm_node_t *p_node;
+ const osm_physp_t *p_physp;
+ const osm_physp_t *p_remote_physp;
+ const ib_port_info_t *p_pi;
+ uint8_t port_num;
+ uint8_t start_port;
+ uint32_t num_ports;
+ char line[OSM_REPORT_LINE_SIZE];
+ uint8_t node_type;
+ uint32_t line_num = 0;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report );
+
+ if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ goto Exit;
+ }
+
+ p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ * Hold lock non-exclusively while we perform these read-only operations.
+ */
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_head( p_tbl );
+ while( p_port != ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_report: "
+ "Processing port 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ node_type = osm_node_get_type( p_node );
+ if( node_type == IB_NODE_TYPE_SWITCH )
+ start_port = 0;
+ else
+ start_port = 1;
+
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = start_port; port_num < num_ports; port_num++ )
+ {
+ if( line_num == 0 )
+ {
+ strcpy( p_mgr->p_report_buf,
+ "\n==================================================="
+ "====================================================" );
+ strcat( p_mgr->p_report_buf,
+ "\nVendor : Ty "
+ ": # : Sta : LID : LMC : MTU : LWA : LSA : Port GUID "
+ " : Neighbor Port (Port #)\n" );
+ line_num++;
+ }
+
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+ continue;
+
+ sprintf( line, "%s : %s : %02X :",
+ osm_get_manufacturer_str( cl_ntoh64
+ ( osm_node_get_node_guid
+ ( p_node ) ) ),
+ osm_get_node_type_str_fixed_width( node_type ), port_num );
+
+ strcat( p_mgr->p_report_buf, line );
+
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /*
+ * Port state is not defined for switch port 0
+ */
+ if( port_num == 0 )
+ strcat( p_mgr->p_report_buf, " :" );
+ else
+ {
+ sprintf( line, " %s :",
+ osm_get_port_state_str_fixed_width
+ ( ib_port_info_get_port_state( p_pi ) ) );
+ strcat( p_mgr->p_report_buf, line );
+ }
+
+ /*
+ * LID values are only meaningful in select cases.
+ */
+ if( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN )
+ {
+ if( ( ( node_type == IB_NODE_TYPE_SWITCH ) && ( port_num == 0 ) )
+ || ( node_type != IB_NODE_TYPE_SWITCH ) )
+ {
+ sprintf( line, " %04X : %01X :",
+ cl_ntoh16( p_pi->base_lid ),
+ ib_port_info_get_lmc( p_pi ) );
+
+ strcat( p_mgr->p_report_buf, line );
+ }
+ else
+ strcat( p_mgr->p_report_buf, " : :" );
+ }
+ else
+ strcat( p_mgr->p_report_buf, " : :" );
+
+ if( port_num != 0 )
+ {
+ sprintf( line, " %s : %s : %s ",
+ osm_get_mtu_str( ib_port_info_get_neighbor_mtu( p_pi ) ),
+ osm_get_lwa_str( p_pi->link_width_active ),
+ osm_get_lsa_str( ib_port_info_get_link_speed_active
+ ( p_pi ) ) );
+ }
+ else
+ {
+ sprintf( line, " %s : %s : %s ", " ", " ", " " );
+ }
+ strcat( p_mgr->p_report_buf, line );
+
+ if( osm_physp_get_port_guid( p_physp ) ==
+ p_mgr->p_subn->sm_port_guid )
+ {
+ sprintf( line, "* %016" PRIx64 " *",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ else
+ {
+ sprintf( line, ": %016" PRIx64 " :",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ strcat( p_mgr->p_report_buf, line );
+
+ if( port_num &&
+ ( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN ) )
+ {
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ sprintf( line, " %016" PRIx64 " (%02X)",
+ cl_ntoh64( osm_physp_get_port_guid
+ ( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ) );
+ strcat( p_mgr->p_report_buf, line );
+ }
+ else
+ strcat( p_mgr->p_report_buf, " UNKNOWN" );
+ }
+
+ strcat( p_mgr->p_report_buf, "\n" );
+
+ if( ++line_num >= OSM_REPORT_BUF_THRESHOLD )
+ {
+ osm_log_raw( p_mgr->p_log, OSM_LOG_VERBOSE, p_mgr->p_report_buf );
+ line_num = 0;
+ }
+ }
+ strcat( p_mgr->p_report_buf,
+ "------------------------------------------------------"
+ "------------------------------------------------\n" );
+ p_port = ( osm_port_t * ) cl_qmap_next( &p_port->map_item );
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ if( line_num != 0 )
+ osm_log_raw( p_mgr->p_log, OSM_LOG_VERBOSE, p_mgr->p_report_buf );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__process_idle_time_queue_done(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qlist_t *p_list = &p_mgr->idle_time_list;
+ cl_list_item_t *p_list_item;
+ osm_idle_item_t *p_process_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_done );
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+ p_list_item = cl_qlist_remove_head( p_list );
+
+ if( p_list_item == cl_qlist_end( p_list ) )
+ {
+ cl_spinlock_release( &p_mgr->idle_lock );
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__process_idle_time_queue_done: ERR 3314: "
+ "Idle time queue is empty.\n" );
+ return;
+ }
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+ if( p_process_item->pfn_done )
+ {
+
+ p_process_item->pfn_done( p_process_item->context1,
+ p_process_item->context2 );
+ }
+
+
+ cl_free( p_process_item );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__process_idle_time_queue_start(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qlist_t *p_list = &p_mgr->idle_time_list;
+ cl_list_item_t *p_list_item;
+ osm_idle_item_t *p_process_item;
+ osm_signal_t signal;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_start );
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+
+ p_list_item = cl_qlist_head( p_list );
+ if( p_list_item == cl_qlist_end( p_list ) )
+ {
+ cl_spinlock_release( &p_mgr->idle_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return OSM_SIGNAL_NONE;
+ }
+
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+ CL_ASSERT( p_process_item->pfn_start );
+
+ signal = p_process_item->pfn_start( p_process_item->context1,
+ p_process_item->context2 );
+
+ CL_ASSERT( signal != OSM_SIGNAL_NONE );
+
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return signal;
+}
+
+/**********************************************************************
+ * Go over all the remote SMs (as update in the sm_guid_tbl).
+ * Find if there is a remote sm that is a master SM.
+ * If there is a remote master SM - return TRUE, else - return FALSE.
+ **********************************************************************/
+osm_remote_sm_t *
+__osm_state_mgr_exists_other_master(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qmap_t *p_sm_tbl;
+ osm_remote_sm_t *p_sm;
+ osm_remote_sm_t *p_sm_res = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_exists_other_master );
+
+ p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+ /* go over all the remote SMs */
+ for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl );
+ p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl );
+ p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) )
+ {
+ /* If the sm is in MASTER state - return TRUE */
+ if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_exists_other_master: "
+ "Found remote master sm with guid:0x%X \n",
+ p_sm->smi.guid );
+ p_sm_res = p_sm;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( p_sm_res );
+}
+
+/**********************************************************************
+ * Go over all remote SMs (as updated in the sm_guid_tbl).
+ * Find the one with the highest priority and lowest guid.
+ * Compare this SM to the local SM. If the local SM is higher -
+ * return NULL, if the remote SM is higher - return a pointer to it.
+ **********************************************************************/
+osm_remote_sm_t *
+__osm_state_mgr_get_highest_sm(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qmap_t *p_sm_tbl;
+ osm_remote_sm_t *p_sm = NULL;
+ osm_remote_sm_t *p_highest_sm;
+ uint8_t highest_sm_priority;
+ ib_net64_t highest_sm_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_highest_sm );
+
+ p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+ /* Start with the local sm as the standard */
+ p_highest_sm = NULL;
+ highest_sm_priority = p_mgr->p_subn->opt.sm_priority;
+ highest_sm_guid = p_mgr->p_subn->sm_port_guid;
+
+ /* go over all the remote SMs */
+ for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl );
+ p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl );
+ p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) )
+ {
+
+ /* If the sm is in NOTACTIVE state - continue */
+ if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_NOTACTIVE )
+ continue;
+
+ if( osm_sm_is_greater_than( ib_sminfo_get_priority( &p_sm->smi ),
+ p_sm->smi.guid, highest_sm_priority,
+ highest_sm_guid ) )
+ {
+ /* the new p_sm is with higher priority - update the highest_sm */
+ /* to this sm */
+ p_highest_sm = p_sm;
+ highest_sm_priority = ib_sminfo_get_priority( &p_sm->smi );
+ highest_sm_guid = p_sm->smi.guid;
+ }
+ }
+
+ if( p_highest_sm != NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_get_highest_sm: "
+ "Found higher SM with guid: %016" PRIx64 "\n",
+ cl_ntoh64( p_highest_sm->smi.guid ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( p_highest_sm );
+}
+
+/**********************************************************************
+ * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
+ * remote_sm given.
+ **********************************************************************/
+void
+__osm_state_mgr_send_handover(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_remote_sm_t * const p_sm )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_sm_info_t *p_smi = ( ib_sm_info_t * ) payload;
+ osm_madw_context_t context;
+ const osm_port_t *p_port;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_send_handover );
+
+ if( p_mgr->p_subn->opt.testability_mode ==
+ OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3315: "
+ "Exit on testablity mode OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER\n" );
+ osm_exit_flag = TRUE;
+ sleep( 3 );
+ exit( 1 );
+ }
+
+ /*
+ * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given.
+ */
+
+ cl_memclr( &context, sizeof( context ) );
+ p_port = p_sm->p_port;
+ if( p_port == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3316: "
+ "No port object on given remote_sm object\n" );
+ goto Exit;
+ }
+
+ /* update the master_guid in the p_sm_state_mgr object according to */
+ /* the guid of the port where the new Master SM should reside. */
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_send_handover: "
+ "Handover mastership. Updating sm_state_mgr master_guid: %016"
+ PRIx64 "\n", cl_ntoh64( p_port->guid ) );
+ p_mgr->p_sm_state_mgr->master_guid = p_port->guid;
+
+ context.smi_context.port_guid = p_port->guid;
+ context.smi_context.set_method = TRUE;
+
+ p_smi->guid = p_mgr->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_mgr->p_stats->qp0_mads_sent );
+ p_smi->pri_state = ( uint8_t ) ( p_mgr->p_subn->sm_state |
+ p_mgr->p_subn->opt.sm_priority << 4 );
+ /*
+ * Return 0 for the SM key unless we authenticate the requestor
+ * as the master SM.
+ */
+ if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_send_handover: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_mgr->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requestor is not authenticated as master - set sm_key to zero */
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_send_handover: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ status = osm_req_set( p_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ), payload,
+ IB_MAD_ATTR_SM_INFO, IB_SMINFO_ATTR_MOD_HANDOVER,
+ CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3317: "
+ "Failure requesting SMInfo (%s).\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+}
+
+
+/**********************************************************************
+ * Send Trap 64 on all ports in new_ports_list.
+ **********************************************************************/
+void
+__osm_state_mgr_report_new_ports(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ osm_port_t *p_port;
+ ib_gid_t port_gid;
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+ ib_net64_t port_guid;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report_new_ports );
+
+ p_port =
+ ( osm_port_t
+ * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+ while( p_port != NULL )
+ {
+ port_guid = osm_port_get_guid( p_port );
+ /* issue a notice - trap 64 */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type( ¬ice, CL_HTON32( 4 ) ); /* A Class Manager generator */
+ /* endport becomes to be reachable */
+ notice.g_or_v.generic.trap_num = CL_HTON16( 64 );
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+ /* following C14-72.1.1 and table 119 p725 */
+ /* we need to provide the GID */
+ port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+ port_gid.unicast.interface_id = port_guid;
+ cl_memcpy( &( notice.data_details.ntc_64_67.gid ),
+ &( port_gid ), sizeof( ib_gid_t ) );
+
+ /* According to page 653 - the issuer gid in this case of trap
+ * is the SM gid, since the SM is the initiator of this trap. */
+ notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+ status = osm_report_notice( p_mgr->p_log, p_mgr->p_subn, ¬ice );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_report_new_ports: ERR 3318: "
+ "Error sending trap reports on GUID:0x%016" PRIx64
+ " (%s).\n", port_gid.unicast.interface_id,
+ ib_get_err_str( status ) );
+ }
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+ osm_log( p_mgr->p_log, OSM_LOG_INFO,
+ "Discovered new port with GUID:0x%016" PRIx64
+ " LID range [0x%X,0x%X] of node:%s \n",
+ cl_ntoh64( port_gid.unicast.interface_id ),
+ min_lid_ho, max_lid_ho,
+ ( p_port->p_node ?
+ ( char * )( p_port->p_node->node_desc.description ) :
+ "UNKNOWN" ) );
+
+ p_port =
+ ( osm_port_t
+ * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ * Make sure that the lid_port_tbl of the subnet has only the ports
+ * that are recognized, and in the correct lid place. There could be
+ * errors if we wanted to assign to a certain port with lid X, but that
+ * request didn't reach the port. In this case port_lid_tbl will have
+ * the port under lid X, though the port isn't updated with this lid.
+ * We will run a new heavy sweep (since there were errors in the
+ * initialization), but here we'll clean the database from incorrect
+ * information.
+ **********************************************************************/
+void
+__osm_state_mgr_check_tbl_consistency(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qmap_t *p_port_guid_tbl;
+ osm_port_t *p_port;
+ osm_port_t *p_next_port;
+ cl_ptr_vector_t *p_port_lid_tbl;
+ size_t max_lid, ref_size, curr_size, lid;
+ osm_port_t *p_port_ref, *p_port_stored;
+ cl_ptr_vector_t ref_port_lid_tbl;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_check_tbl_consistency );
+
+ cl_ptr_vector_construct( &ref_port_lid_tbl );
+ cl_ptr_vector_init( &ref_port_lid_tbl,
+ cl_ptr_vector_get_size( &p_mgr->p_subn->port_lid_tbl ),
+ OSM_SUBNET_VECTOR_GROW_SIZE );
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /* Let's go over all the ports according to port_guid _tbl,
+ * and add the port to a reference port_lid_tbl. */
+ p_next_port = ( osm_port_t * ) cl_qmap_head( p_port_guid_tbl );
+ while( p_next_port != ( osm_port_t * ) cl_qmap_end( p_port_guid_tbl ) )
+ {
+ p_port = p_next_port;
+ p_next_port = ( osm_port_t * ) cl_qmap_next( &p_next_port->map_item );
+
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+ for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ cl_ptr_vector_set( &ref_port_lid_tbl, lid_ho, p_port );
+ }
+
+ p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl;
+
+ ref_size = cl_ptr_vector_get_size( &ref_port_lid_tbl );
+ curr_size = cl_ptr_vector_get_size( p_port_lid_tbl );
+ /* They should be the same, but compare it anyways */
+ max_lid = ( ref_size > curr_size ) ? ref_size : curr_size;
+
+ for( lid = 1; lid <= max_lid; lid++ )
+ {
+ p_port_ref = NULL;
+ p_port_stored = NULL;
+ cl_ptr_vector_at( p_port_lid_tbl, lid, ( void * )&p_port_stored );
+ cl_ptr_vector_at( &ref_port_lid_tbl, lid, ( void * )&p_port_ref );
+
+ if( p_port_stored == p_port_ref )
+ /* This is the "good" case - both entries are the same for this lid.
+ * Nothing to do. */
+ continue;
+
+ if( p_port_ref == NULL )
+ {
+ /* There is an object in the subnet database for this lid,
+ * but no such object exists in the reference port_list_tbl.
+ * This can occure if we wanted to assign a certain port with some
+ * lid (different than the one pre-assigned to it), and the port
+ * didn't get the portInfo Set request. Due to that, the port
+ * is updated with its original lid in our data-base, but with the
+ * new lid we wanted to give it in our port_lid_tbl. */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3322: "
+ "lid 0x%X is wrongly assigned to port 0x%016" PRIx64
+ " in port_lid_tbl\n",
+ lid, cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+ }
+ else
+ {
+ if( p_port_stored == NULL )
+ {
+ /* There is an object in the new database, but no object in our subnet
+ * database. This is the matching case of the prior check - the port
+ * still has its original lid. */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3323: "
+ "port 0x%016" PRIx64 " exists in new port_lid_tbl under "
+ "lid 0x%X, but missing in subnet port_lid_tbl db\n",
+ cl_ntoh64( osm_port_get_guid( p_port_ref ) ), lid );
+ }
+ else
+ {
+
+ /* if we reached here then p_port_stored != p_port_ref.
+ * We were trying to set a lid to p_port_stored, but it didn't reach it,
+ * and p_port_ref also didn't get the lid update. */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3324: "
+ "lid 0x%X has port 0x%016" PRIx64
+ " in new port_lid_tbl db, " "and port 0x%016" PRIx64
+ " in subnet port_lid_tbl db\n", lid,
+ cl_ntoh64( osm_port_get_guid( p_port_ref ) ),
+ cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+ }
+ }
+ /* In any of these cases we want to set NULL in the port_lid_tbl, since this
+ * entry is invalid. Also, make sure we'll do another heavy sweep. */
+ cl_ptr_vector_set( p_port_lid_tbl, lid, NULL );
+ p_mgr->p_subn->subnet_initialization_error = TRUE;
+ }
+
+ cl_ptr_vector_destroy( &ref_port_lid_tbl );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_process(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_signal_t signal )
+{
+ ib_api_status_t status;
+ osm_remote_sm_t *p_remote_sm;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process );
+ CL_ASSERT( p_mgr );
+
+ /* if we are exiting do nothing */
+ if( osm_exit_flag )
+ signal = OSM_SIGNAL_NONE;
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process. For example, if an function
+ * puts transactions on the wire, the state lock guarantees this
+ * loop will see the return code ("DONE PENDING") of the function
+ * before the "NO OUTSTANDING TRANSACTIONS" signal is asynchronously
+ * received.
+ */
+ cl_spinlock_acquire( &p_mgr->state_lock );
+
+ while( signal != OSM_SIGNAL_NONE )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_state_mgr_process: "
+ "Received signal %s in state %s.\n",
+ osm_get_sm_signal_str( signal ),
+ osm_get_sm_state_str( p_mgr->state ) );
+ }
+
+ /*
+ * If we're already sweeping and we get the signal to sweep,
+ * just ignore it harmlessly.
+ */
+ if( ( p_mgr->state != OSM_SM_STATE_IDLE ) &&
+ ( p_mgr->state != OSM_SM_STATE_STANDBY ) &&
+ ( signal == OSM_SIGNAL_SWEEP ) )
+ {
+ break;
+ }
+
+ switch ( p_mgr->state )
+ {
+ case OSM_SM_STATE_IDLE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_SWEEP:
+ /*
+ * If the osm_sm_state_mgr is in INIT state - signal
+ * it with a INIT signal to move it to DISCOVERY state.
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_INIT )
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_INIT );
+
+ /*
+ * If we already have switches, then try a light sweep.
+ * Otherwise, this is probably our first discovery pass
+ * or we are connected in loopback. In both cases do a
+ * heavy sweep.
+ * Note: If we are connected in loopback we want a heavy
+ * sweep, since we will not be getting any traps if there is
+ * a lost connection.
+ */
+ /* if we are in DISCOVERING state - this means it is either in
+ * initializing or wake up from STANDBY - run the heavy sweep */
+ if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) &&
+ p_mgr->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING &&
+ p_mgr->p_subn->opt.force_heavy_sweep == FALSE &&
+ p_mgr->p_subn->force_immediate_heavy_sweep == FALSE &&
+ p_mgr->p_subn->force_delayed_heavy_sweep == FALSE &&
+ p_mgr->p_subn->subnet_initialization_error == FALSE )
+ {
+ if( __osm_state_mgr_light_sweep_start( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT;
+ }
+ }
+ else
+ {
+ /* First of all - if force_immediate_heavy_sweep is TRUE then
+ * need to unset it */
+ p_mgr->p_subn->force_immediate_heavy_sweep = FALSE;
+ /* If force_delayed_heavy_sweep is TRUE then
+ * need to unset it */
+ p_mgr->p_subn->force_delayed_heavy_sweep = FALSE;
+ /* If subnet_initialization_error is TRUE then
+ * need to unset it. */
+ p_mgr->p_subn->subnet_initialization_error = FALSE;
+
+ status = __osm_state_mgr_sweep_hop_0( p_mgr );
+ if( status == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+ }
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+ case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+ case OSM_SM_STATE_PROCESS_REQUEST:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_IDLE_TIME_PROCESS:
+ signal = __process_idle_time_queue_start( p_mgr );
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NONE:
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+ break;
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+ case OSM_SM_STATE_PROCESS_REQUEST_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+ break;
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+ case OSM_SM_STATE_PROCESS_REQUEST_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* CALL the done function */
+ __process_idle_time_queue_done( p_mgr );
+
+ /*
+ * Set the signal to OSM_SIGNAL_IDLE_TIME_PROCESS
+ * so that the next element in the queue gets processed
+ */
+
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ break;
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+ case OSM_SM_STATE_SWEEP_LIGHT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing else to do yet except change state.
+ */
+ p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * No change was detected on the subnet.
+ * We can return to the idle state.
+ */
+ __osm_state_mgr_light_sweep_done_msg( p_mgr );
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SWEEP_LIGHT_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another....
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * A change was detected on the subnet.
+ * Initiate a heavy sweep.
+ */
+ if( __osm_state_mgr_sweep_hop_0( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ break;
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SM_STATE_SWEEP_HEAVY_SELF:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another....
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ if( __osm_state_mgr_is_sm_port_down( p_mgr ) == TRUE )
+ {
+ __osm_state_mgr_sm_port_down_msg( p_mgr );
+
+ /* Run the drop manager - we want to clear all records */
+ osm_drop_mgr_process( p_mgr->p_drop_mgr );
+
+ /* Move to DISCOVERING state */
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_DISCOVER );
+
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ }
+ else
+ {
+ if( __osm_state_mgr_sweep_hop_1( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SUBNET;
+ }
+ signal = OSM_SIGNAL_NONE;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ break;
+
+ /*
+ * There is no 'OSM_SM_STATE_SWEEP_HEAVY_WAIT' state since we
+ * know that there outstanding transaction on the wire already...
+ */
+ case OSM_SM_STATE_SWEEP_HEAVY_SUBNET:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another....
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ p_mgr->state = OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED;
+ break;
+
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ __osm_state_mgr_sweep_heavy_done_msg( p_mgr );
+
+ /* If we are MASTER - get the highest remote_sm, and
+ * see if it is higher than our local sm. If
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ p_remote_sm = __osm_state_mgr_get_highest_sm( p_mgr );
+ if( p_remote_sm != NULL )
+ {
+ /* need to handover the mastership
+ * to the remote sm, and move to standby */
+ __osm_state_mgr_send_handover( p_mgr, p_remote_sm );
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_HANDOVER_SENT );
+ p_mgr->state = OSM_SM_STATE_STANDBY;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ else
+ {
+ /* We are the highest sm - check to see if there is
+ * a remote SM that is in master state. */
+ p_remote_sm = __osm_state_mgr_exists_other_master( p_mgr );
+ if( p_remote_sm != NULL )
+ {
+ /* There is a remote SM that is master.
+ * need to wait for that SM to relinquish control
+ * of its portion of the subnet. C14-60.
+ * Also - need to start polling on that SM. */
+ p_mgr->p_sm_state_mgr->p_polling_sm = p_remote_sm;
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_WAIT_FOR_HANDOVER );
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+ }
+ }
+ }
+ /* Need to continue with lid assigning */
+ osm_drop_mgr_process( p_mgr->p_drop_mgr );
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID;
+
+ /*
+ * If we are not MASTER already - this means that we are
+ * in discovery state. call osm_sm_state_mgr with signal
+ * DISCOVERY_COMPLETED
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_DISCOVERY_COMPLETED );
+
+ signal = osm_lid_mgr_process_sm( p_mgr->p_lid_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ {
+ __osm_state_mgr_set_sm_lid_done_msg( p_mgr );
+ __osm_state_mgr_notify_lid_change( p_mgr );
+ }
+
+ /* Break on single step mode - if not continuous */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS;
+ signal = osm_lid_mgr_process_subnet( p_mgr->p_lid_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ /*
+ * The LID Manager is done processing.
+ * There are no outstanding transactions, so we
+ * can move on to configuring the forwarding tables.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The LID Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ /*
+ * In this state, the Unicast Manager has completed processing,
+ * but there are still transactions on the wire. Therefore,
+ * wait here until the wire clears.
+ */
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * The LID Manager is done processing.
+ * There are no outstanding transactions, so we
+ * can move on to configuring the forwarding tables.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE:
+
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /* At this point we need to check the consistency of
+ * the port_lid_tbl under the subnet. There might be
+ * errors in it if PortInfo Set reqeusts didn't reach
+ * their destination. */
+ __osm_state_mgr_check_tbl_consistency( p_mgr );
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_lid_assign_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ /*
+ * OK, the wire is clear, so proceed with
+ * unicast forwarding table configuration.
+ * First - send trap 64 on newly discovered endports
+ */
+ __osm_state_mgr_report_new_ports( p_mgr );
+
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES;
+ signal = osm_ucast_mgr_process( p_mgr->p_ucast_mgr );
+
+ /* Break on single step mode */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_CONTINUOUS )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ }
+
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Unicast Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* we are done setting all LFTs so clear the ignore existing.
+ * From now on, as long as we are still master, we want to
+ * take into account these lfts. */
+ p_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_switch_config_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+
+ if( !p_mgr->p_subn->opt.disable_multicast )
+ {
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES;
+ signal = osm_mcast_mgr_process( p_mgr->p_mcast_mgr );
+ }
+ else
+ {
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_NO_CHANGE );
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Multicast Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_multicast_config_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_NO_CHANGE );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ /*
+ * The LINK_PORTS state is required since we can not count on
+ * the port state change MADs to succeed. This is an artifact
+ * of the spec defining state change from state X to state X
+ * as an error. The Hardware then is not required to process
+ * other parameters provided by the Set(PortInfo) Packet.
+ */
+ case OSM_SM_STATE_SET_LINK_PORTS:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_LINK_PORTS_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_LINK_PORTS_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+
+ __osm_state_mgr_links_ports_msg( p_mgr );
+
+ p_mgr->state = OSM_SM_STATE_SET_ARMED;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr, IB_LINK_ARMED );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_links_armed_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_ACTIVE;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_ACTIVE );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ACTIVE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ /*
+ * Don't change the signal, just the state.
+ */
+ p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_ACTIVE_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ACTIVE_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * Don't change the signal, just the state.
+ */
+ p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SUBNET_UP:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /*
+ * The sweep completed!
+ */
+
+ /* in any case we zero this flag */
+ p_mgr->p_subn->coming_out_of_standby = FALSE;
+
+ /* If there were errors - then the subnet is not really up */
+ if( p_mgr->p_subn->subnet_initialization_error == TRUE )
+ {
+ __osm_state_mgr_init_errors_msg( p_mgr );
+ }
+ else
+ {
+ /* The subnet is up correctly - set the first_time_master_sweep flag
+ * (if it is on) to FALSE. */
+ if( p_mgr->p_subn->first_time_master_sweep == TRUE )
+ {
+ p_mgr->p_subn->first_time_master_sweep = FALSE;
+ }
+
+ osm_topology_file_create( p_mgr );
+ __osm_state_mgr_report( p_mgr );
+ __osm_state_mgr_up_msg( p_mgr );
+ }
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+
+ /*
+ * Finally signal the subnet up event
+ */
+ status = cl_event_signal( p_mgr->p_subnet_up_event );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process: ERR 3319: "
+ "Invalid SM state %u.\n", p_mgr->state );
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+
+ case OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another....
+ */
+ break;
+
+ case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ /*
+ * If we lost once, we might lose again. Nothing to do.
+ */
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_STANDBY;
+ /*
+ * Call the sm_state_mgr with signal
+ * MASTER_OR_HIGHER_SM_DETECTED_DONE
+ */
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE );
+ __osm_state_mgr_standby_msg( p_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ break;
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+
+ case OSM_SM_STATE_STANDBY:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_EXIT_STBY:
+ /*
+ * Need to force re-write of sm_base_lid to all ports
+ * to do that we want all the ports to be considered
+ * foriegn
+ */
+ signal = OSM_SIGNAL_SWEEP;
+ __osm_state_mgr_clean_known_lids( p_mgr );
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ break;
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * Nothing to do here - need to stay at this state
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ /* stay with the same signal - so we can start the sweep */
+ break;
+
+ default:
+ CL_ASSERT( FALSE );
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process: ERR 3320: "
+ "Invalid SM state %u.\n", p_mgr->state );
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ /* if we got a signal to force immediate heavy sweep in the middle of the sweep -
+ * try another sweep. */
+ if( ( p_mgr->p_subn->force_immediate_heavy_sweep ) &&
+ ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+ {
+ signal = OSM_SIGNAL_SWEEP;
+ }
+ /* if we got errors during the initialization in the middle of the sweep -
+ * try another sweep. */
+ if( ( p_mgr->p_subn->subnet_initialization_error ) &&
+ ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+ {
+ signal = OSM_SIGNAL_SWEEP;
+ }
+
+
+ /*
+ * for single step mode - some stages need to break only
+ * after evaluating a single step.
+ * For those we track the fact we have already performed
+ * a single loop
+ */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_TAKE_ONE )
+ p_mgr->state_step_mode = OSM_STATE_STEP_BREAK;
+ }
+
+ cl_spinlock_release( &p_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_process_idle(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_pfn_start_t pfn_start,
+ IN osm_pfn_done_t pfn_done,
+ void *context1,
+ void *context2 )
+{
+ osm_idle_item_t *p_idle_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process_idle );
+
+ p_idle_item = cl_zalloc( sizeof( osm_idle_item_t ) );
+ if( p_idle_item == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process_idle: ERR 3321: "
+ "insufficient memory\n" );
+ return IB_ERROR;
+ }
+
+
+ p_idle_item->pfn_start = pfn_start;
+ p_idle_item->pfn_done = pfn_done;
+ p_idle_item->context1 = context1;
+ p_idle_item->context2 = context2;
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+ cl_qlist_insert_tail( &p_mgr->idle_time_list, &p_idle_item->list_item );
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ osm_state_mgr_process( p_mgr, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ return IB_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_ctrl_t.
+ * This object represents the State Manager Controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x1601
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_state_mgr_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_state_mgr_process( ((osm_state_mgr_ctrl_t*)context)->p_mgr,
+ (osm_signal_t)(p_data) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_construct(
+ IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_destroy(
+ IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+ IN osm_state_mgr_ctrl_t* const p_ctrl,
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_state_mgr_ctrl_init );
+
+ osm_state_mgr_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_mgr = p_mgr;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ __osm_state_mgr_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_ctrl_init: ERR 3401: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+#include <stdlib.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_construct(
+ IN osm_subn_t* const p_subn )
+{
+ cl_memclr( p_subn, sizeof(*p_subn) );
+ cl_ptr_vector_construct( &p_subn->node_lid_tbl );
+ cl_ptr_vector_construct( &p_subn->port_lid_tbl );
+ cl_qmap_init( &p_subn->sw_guid_tbl );
+ cl_qmap_init( &p_subn->node_guid_tbl );
+ cl_qmap_init( &p_subn->port_guid_tbl );
+ cl_qmap_init( &p_subn->sm_guid_tbl );
+ cl_qlist_init( &p_subn->sa_sr_list );
+ cl_qlist_init( &p_subn->sa_infr_list );
+ cl_qmap_init( &p_subn->rtr_guid_tbl );
+ cl_qmap_init( &p_subn->prtn_pkey_tbl );
+ cl_qmap_init( &p_subn->mgrp_mlid_tbl );
+ cl_list_construct( &p_subn->new_ports_list );
+ cl_list_init( &p_subn->new_ports_list, 10 );
+ cl_list_construct( &p_subn->light_sweep_physp_list );
+ cl_list_init( &p_subn->light_sweep_physp_list, 5 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_destroy(
+ IN osm_subn_t* const p_subn )
+{
+ osm_node_t *p_node, *p_next_node;
+ osm_port_t *p_port, *p_next_port;
+ osm_switch_t *p_sw, *p_next_sw;
+ osm_remote_sm_t *p_rsm, *p_next_rsm;
+ osm_mgrp_t *p_mgrp, *p_next_mgrp;
+ osm_infr_t *p_infr, *p_next_infr;
+
+ /* it might be a good idea to de-allocate all known objects */
+ p_next_node = (osm_node_t*)cl_qmap_head( &p_subn->node_guid_tbl );
+ while( p_next_node != (osm_node_t*)cl_qmap_end( &p_subn->node_guid_tbl ) )
+ {
+ p_node = p_next_node;
+ p_next_node = (osm_node_t*)cl_qmap_next( &p_node->map_item );
+ osm_node_delete( &p_node );
+ }
+
+ cl_ptr_vector_destroy( &p_subn->node_lid_tbl );
+
+ p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl );
+ while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) )
+ {
+ p_port = p_next_port;
+ p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+ osm_port_delete( &p_port );
+ }
+
+ p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl );
+ while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) )
+ {
+ p_sw = p_next_sw;
+ p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ osm_switch_delete( &p_sw );
+ }
+
+ p_next_rsm = (osm_remote_sm_t*)cl_qmap_head( &p_subn->sm_guid_tbl );
+ while( p_next_rsm != (osm_remote_sm_t*)cl_qmap_end( &p_subn->sm_guid_tbl ) )
+ {
+ p_rsm = p_next_rsm;
+ p_next_rsm = (osm_remote_sm_t*)cl_qmap_next( &p_rsm->map_item );
+ cl_free( p_rsm );
+ }
+
+ p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+ while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+ {
+ p_mgrp = p_next_mgrp;
+ p_next_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ osm_mgrp_destroy( p_mgrp );
+ }
+
+ p_next_infr = (osm_infr_t*)cl_qlist_head( &p_subn->sa_infr_list );
+ while (p_next_infr != (osm_infr_t*)cl_qlist_end( &p_subn->sa_infr_list ) )
+ {
+ p_infr = p_next_infr;
+ p_next_infr = (osm_infr_t*)cl_qlist_next( &p_infr->list_item );
+ osm_infr_destroy( p_infr );
+ }
+
+ cl_list_remove_all( &p_subn->new_ports_list );
+ cl_list_destroy( &p_subn->new_ports_list );
+
+ cl_list_remove_all( &p_subn->light_sweep_physp_list );
+ cl_list_destroy( &p_subn->light_sweep_physp_list );
+
+ cl_ptr_vector_destroy( &p_subn->port_lid_tbl );
+ cl_map_remove_all(&(p_subn->opt.port_pro_ignore_guids));
+ cl_map_destroy(&(p_subn->opt.port_pro_ignore_guids));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_subn_init(
+ IN osm_subn_t* const p_subn,
+ IN const osm_subn_opt_t* const p_opt )
+{
+ cl_status_t status;
+
+ status = cl_ptr_vector_init( &p_subn->node_lid_tbl,
+ OSM_SUBNET_VECTOR_MIN_SIZE,
+ OSM_SUBNET_VECTOR_GROW_SIZE );
+ if( status != CL_SUCCESS )
+ return( status );
+
+ status = cl_ptr_vector_init( &p_subn->port_lid_tbl,
+ OSM_SUBNET_VECTOR_MIN_SIZE,
+ OSM_SUBNET_VECTOR_GROW_SIZE );
+ if( status != CL_SUCCESS )
+ return( status );
+
+ status = cl_ptr_vector_set_capacity( &p_subn->node_lid_tbl,
+ OSM_SUBNET_VECTOR_CAPACITY );
+ if( status != CL_SUCCESS )
+ return( status );
+
+ status = cl_ptr_vector_set_capacity( &p_subn->port_lid_tbl,
+ OSM_SUBNET_VECTOR_CAPACITY );
+ if( status != CL_SUCCESS )
+ return( status );
+
+ /*
+ LID zero is not valid. NULL out this entry for the
+ convenience of other code.
+ */
+ cl_ptr_vector_set( &p_subn->node_lid_tbl, 0, NULL );
+ cl_ptr_vector_set( &p_subn->port_lid_tbl, 0, NULL );
+
+ p_subn->opt = *p_opt;
+ p_subn->max_unicast_lid_ho = IB_LID_UCAST_END_HO;
+ p_subn->max_multicast_lid_ho = IB_LID_MCAST_END_HO;
+ p_subn->min_ca_mtu = IB_MAX_MTU;
+ p_subn->min_ca_rate = IB_MAX_RATE;
+
+ /* note that insert and remove are part of the port_profile thing. */
+ cl_map_init(&(p_subn->opt.port_pro_ignore_guids), 10);
+
+ /* ignore_existing_lfts follows the reassign_lfts on first sweep */
+ p_subn->ignore_existing_lfts = p_subn->opt.reassign_lfts;
+
+ /* we assume master by default - so we only need to set it true if STANDBY */
+ p_subn->coming_out_of_standby = FALSE;
+
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_gid_t
+osm_get_gid_by_mad_addr(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t *p_subn,
+ IN const osm_mad_addr_t *p_mad_addr )
+{
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const osm_physp_t* p_physp = NULL;
+ ib_gid_t request_gid;
+
+ /* Find the port gid of the request in the subnet */
+ p_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+ request_gid.unicast.interface_id = p_physp->port_guid;
+ request_gid.unicast.prefix = p_subn->opt.subnet_prefix;
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_gid_by_mad_addr: ERR 7501 "
+ "Lid is out of range: 0x%X \n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ }
+
+ return request_gid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_physp_t*
+osm_get_physp_by_mad_addr(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t *p_subn,
+ IN osm_mad_addr_t *p_mad_addr )
+{
+ const cl_ptr_vector_t* p_port_lid_tbl;
+ osm_port_t* p_port = NULL;
+ osm_physp_t* p_physp = NULL;
+
+ /* Find the port gid of the request in the subnet */
+ p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port = cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ if (p_port == NULL)
+ {
+ /* The port is not in the port_lid table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_physp_by_mad_addr: ERR 7502 "
+ "Cannot locate port object by lid: 0x%X \n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+
+ goto Exit;
+ }
+ p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_physp_by_mad_addr: ERR 7503 "
+ "Lid is out of range: 0x%X \n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+
+ goto Exit;
+ }
+
+ Exit:
+ return p_physp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t*
+osm_get_port_by_mad_addr(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t *p_subn,
+ IN osm_mad_addr_t *p_mad_addr )
+{
+ const cl_ptr_vector_t* p_port_lid_tbl;
+ osm_port_t* p_port = NULL;
+
+ /* Find the port gid of the request in the subnet */
+ p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port =
+ cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_port_by_mad_addr: ERR 7504 "
+ "Lid is out of range: 0x%X \n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ goto Exit;
+ }
+
+ Exit:
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t *
+osm_get_switch_by_guid(
+ IN const osm_subn_t *p_subn,
+ IN uint64_t guid)
+{
+ osm_switch_t *p_switch;
+ p_switch = (osm_switch_t*)cl_qmap_get( &(p_subn->sw_guid_tbl), guid );
+ if( p_switch == (osm_switch_t*)cl_qmap_end( &(p_subn->sw_guid_tbl)) )
+ p_switch = NULL;
+ return p_switch;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t *
+osm_get_node_by_guid(
+ IN osm_subn_t const *p_subn,
+ IN uint64_t guid)
+{
+ osm_node_t *p_node;
+ p_node = (osm_node_t*)cl_qmap_get( &(p_subn->node_guid_tbl), guid );
+ if( p_node == (osm_node_t*)cl_qmap_end( &(p_subn->node_guid_tbl)) )
+ p_node = NULL;
+ return p_node;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t *
+osm_get_port_by_guid(
+ IN osm_subn_t const *p_subn,
+ IN uint64_t guid)
+{
+ osm_port_t *p_port;
+ p_port = (osm_port_t*)cl_qmap_get( &(p_subn->port_guid_tbl), guid );
+ if( p_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
+ p_port = NULL;
+ return p_port;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_set_default_opt(
+ IN osm_subn_opt_t* const p_opt )
+{
+ cl_memclr(p_opt, sizeof(osm_subn_opt_t));
+ p_opt->m_key = OSM_DEFAULT_M_KEY;
+ p_opt->sm_key = OSM_DEFAULT_SM_KEY;
+ p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
+ p_opt->m_key_lease_period = 0;
+ p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
+ p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
+ p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+ /* by default we will consider waiting for 50x transaction timeout normal */
+ p_opt->max_msg_fifo_timeout = 50*OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+ p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
+ p_opt->lmc = OSM_DEFAULT_LMC;
+ p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
+ p_opt->reassign_lids = FALSE;
+ p_opt->reassign_lfts = TRUE;
+ p_opt->ignore_other_sm = FALSE;
+ p_opt->single_thread = FALSE;
+ p_opt->no_multicast_option = FALSE;
+ p_opt->disable_multicast = FALSE;
+ p_opt->force_log_flush = FALSE;
+ p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
+ p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
+ p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
+ p_opt->leaf_head_of_queue_lifetime = OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
+ p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+ p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+ p_opt->sminfo_polling_timeout = OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
+ p_opt->polling_retry_number = 4;
+ p_opt->force_heavy_sweep = FALSE;
+ p_opt->log_flags = 0;
+ p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
+ if (!p_opt->dump_files_dir)
+ p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
+
+ p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+ p_opt->port_profile_switch_nodes = FALSE;
+ p_opt->max_port_profile = 0xffffffff;
+ p_opt->pfn_ui_pre_lid_assign = NULL;
+ p_opt->ui_pre_lid_assign_ctx = NULL;
+ p_opt->pfn_ui_ucast_fdb_assign = NULL;
+ p_opt->ui_ucast_fdb_assign_ctx = NULL;
+ p_opt->pfn_ui_mcast_fdb_assign = NULL;
+ p_opt->ui_mcast_fdb_assign_ctx = NULL;
+ p_opt->sweep_on_trap = TRUE;
+ p_opt->testability_mode = OSM_TEST_MODE_NONE;
+ p_opt->updn_activate = FALSE;
+ p_opt->updn_guid_file = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net64(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint64_t *p_val)
+{
+ uint64_t val;
+ if (!strcmp(p_req_key, p_key))
+ {
+#if __WORDSIZE == 64
+ val = strtoul(p_val_str, NULL, 0);
+#else
+ val = strtoull(p_val_str, NULL, 0);
+#endif
+ if (cl_hton64(val) != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = cl_ntoh64(val);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint32(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint32_t *p_val)
+{
+ uint32_t val;
+ if (!strcmp(p_req_key, p_key))
+ {
+ val = strtoul(p_val_str, NULL, 0);
+ if (val != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %u\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net16(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint16_t *p_val)
+{
+ if (!strcmp(p_req_key, p_key))
+ {
+ uint32_t val;
+ val = strtoul(p_val_str, NULL, 0);
+ CL_ASSERT( val < 0x10000 );
+ if (cl_hton32(val) != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = 0x%04x\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = cl_hton16((uint16_t)val);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint8(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint8_t *p_val)
+{
+
+ if (!strcmp(p_req_key, p_key))
+ {
+ uint32_t val;
+ val = strtoul(p_val_str, NULL, 0);
+ CL_ASSERT( val < 0x100 );
+ if (val != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %u\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = (uint8_t)val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_boolean(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN boolean_t *p_val)
+{
+ if (!strcmp(p_req_key, p_key) && p_val_str)
+ {
+ boolean_t val;
+ if (strcmp("TRUE", p_val_str))
+ val = FALSE;
+ else
+ val = TRUE;
+
+ if (val != *p_val) {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %s\n",
+ p_key, p_val_str);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_charp(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN char **p_val)
+{
+ if (!strcmp(p_req_key, p_key) && p_val_str)
+ {
+ if (strcmp(p_val_str, *p_val))
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %s\n",
+ p_key, p_val_str);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = (char *)cl_malloc(strlen(p_val_str));
+ strcpy( *p_val, p_val_str);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_parse_conf_file(
+ IN osm_subn_opt_t* const p_opts )
+{
+ char *p_cache_dir = getenv("OSM_CACHE_DIR");
+ char file_name[256];
+ FILE *opts_file;
+ char line[1024];
+ char *p_key, *p_val ,*p_last;
+
+ /* try to open the options file from the cache dir */
+ if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+ strcpy(file_name, p_cache_dir);
+ strcat(file_name,"/opensm.opts");
+
+ opts_file = fopen(file_name, "r");
+ if (!opts_file) return;
+
+ while (fgets(line, 1023, opts_file) != NULL)
+ {
+ /* get the first token */
+ p_key = strtok_r(line, " \t\n", &p_last);
+ if (p_key)
+ {
+ p_val = strtok_r(NULL, " \t\n", &p_last);
+
+ __osm_subn_opts_unpack_net64(
+ "m_key", p_key, p_val, &p_opts->m_key);
+
+ __osm_subn_opts_unpack_net64(
+ "sm_key", p_key, p_val, &p_opts->sm_key);
+
+ __osm_subn_opts_unpack_net64(
+ "subnet_prefix",
+ p_key, p_val, &p_opts->subnet_prefix );
+
+ __osm_subn_opts_unpack_net16(
+ "m_key_lease_period",
+ p_key, p_val, &p_opts->m_key_lease_period);
+
+ __osm_subn_opts_unpack_uint32(
+ "sweep_interval",
+ p_key, p_val, &p_opts->sweep_interval);
+
+ __osm_subn_opts_unpack_uint32(
+ "max_wire_smps",
+ p_key, p_val, &p_opts->max_wire_smps);
+
+ __osm_subn_opts_unpack_uint32(
+ "transaction_timeout",
+ p_key, p_val, &p_opts->transaction_timeout);
+
+ __osm_subn_opts_unpack_uint32(
+ "max_msg_fifo_timeout",
+ p_key, p_val, &p_opts->max_msg_fifo_timeout);
+
+ __osm_subn_opts_unpack_uint8(
+ "sm_priority",
+ p_key, p_val, &p_opts->sm_priority);
+
+ __osm_subn_opts_unpack_uint8(
+ "lmc",
+ p_key, p_val, &p_opts->lmc);
+
+ __osm_subn_opts_unpack_uint8(
+ "max_op_vls",
+ p_key, p_val, &p_opts->max_op_vls);
+
+ __osm_subn_opts_unpack_boolean(
+ "reassign_lids",
+ p_key, p_val, &p_opts->reassign_lids);
+
+ __osm_subn_opts_unpack_boolean(
+ "reassign_lfts",
+ p_key, p_val, &p_opts->reassign_lfts);
+
+ __osm_subn_opts_unpack_boolean(
+ "ignore_other_sm",
+ p_key, p_val, &p_opts->ignore_other_sm);
+
+ __osm_subn_opts_unpack_boolean(
+ "single_thread",
+ p_key, p_val, &p_opts->single_thread);
+
+ __osm_subn_opts_unpack_boolean(
+ "no_multicast_option",
+ p_key, p_val, &p_opts->no_multicast_option);
+
+ __osm_subn_opts_unpack_boolean(
+ "disable_multicast",
+ p_key, p_val, &p_opts->disable_multicast);
+
+ __osm_subn_opts_unpack_boolean(
+ "force_log_flush",
+ p_key, p_val, &p_opts->force_log_flush);
+
+ __osm_subn_opts_unpack_uint8(
+ "subnet_timeout",
+ p_key, p_val, &p_opts->subnet_timeout);
+
+ __osm_subn_opts_unpack_uint8(
+ "packet_life_time",
+ p_key, p_val, &p_opts->packet_life_time);
+
+ __osm_subn_opts_unpack_uint8(
+ "head_of_queue_lifetime",
+ p_key, p_val, &p_opts->head_of_queue_lifetime);
+
+ __osm_subn_opts_unpack_uint8(
+ "leaf_head_of_queue_lifetime",
+ p_key, p_val, &p_opts->leaf_head_of_queue_lifetime);
+
+ __osm_subn_opts_unpack_uint8(
+ "local_phy_errors_threshold",
+ p_key, p_val, &p_opts->local_phy_errors_threshold);
+
+ __osm_subn_opts_unpack_uint8(
+ "overrun_errors_threshold",
+ p_key, p_val, &p_opts->overrun_errors_threshold);
+
+ __osm_subn_opts_unpack_uint32(
+ "sminfo_polling_timeout",
+ p_key, p_val, &p_opts->sminfo_polling_timeout);
+
+ __osm_subn_opts_unpack_uint32(
+ "polling_retry_number",
+ p_key, p_val, &p_opts->polling_retry_number);
+
+ __osm_subn_opts_unpack_boolean(
+ "force_heavy_sweep",
+ p_key, p_val, &p_opts->force_heavy_sweep);
+
+ __osm_subn_opts_unpack_uint8(
+ "log_flags",
+ p_key, p_val, &p_opts->log_flags);
+
+ __osm_subn_opts_unpack_boolean(
+ "port_profile_switch_nodes",
+ p_key, p_val, &p_opts->port_profile_switch_nodes);
+
+ __osm_subn_opts_unpack_boolean(
+ "sweep_on_trap",
+ p_key, p_val, &p_opts->sweep_on_trap);
+
+ __osm_subn_opts_unpack_boolean(
+ "updn_activate",
+ p_key, p_val, &p_opts->updn_activate);
+
+ __osm_subn_opts_unpack_charp(
+ "log_file" , p_key, p_val, &p_opts->log_file);
+
+ __osm_subn_opts_unpack_charp(
+ "dump_files_dir" ,
+ p_key, p_val, &p_opts->dump_files_dir);
+
+ __osm_subn_opts_unpack_charp(
+ "updn_guid_file" ,
+ p_key, p_val, &p_opts->updn_guid_file);
+ }
+ }
+ fclose(opts_file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_write_conf_file(
+ IN osm_subn_opt_t* const p_opts )
+{
+ char *p_cache_dir = getenv("OSM_CACHE_DIR");
+ char file_name[256];
+ FILE *opts_file;
+
+ /* try to open the options file from the cache dir */
+ if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+ strcpy(file_name, p_cache_dir);
+ strcat(file_name,"/opensm.opts");
+
+ opts_file = fopen(file_name, "w");
+ if (!opts_file) return;
+
+ fprintf(
+ opts_file,
+ "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
+ "# M_Key value sent to all ports qualifing all Set(PortInfo).\n"
+ "m_key 0x%016" PRIx64 "\n\n"
+ "# The lease period used for the M_Key on this subnet in [msec]\n"
+ "m_key_lease_period %u\n\n"
+ "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n"
+ "sm_key 0x%016" PRIx64 "\n\n"
+ "# Subnet prefix used on this subnet\n"
+ "subnet_prefix 0x%016" PRIx64 "\n\n"
+ "# The LMC value used on this subnet\n"
+ "lmc %u\n\n"
+ "# The code of maximal time a packet can live in a switch\n"
+ "# The actual time is 4.096usec * 2^<packet_life_time code>\n"
+ "# The value 0x14 disables this mechanism\n"
+ "packet_life_time 0x%02x\n\n"
+ "# The code of maximal time a packet can wait at the head of\n"
+ "# transmision queue. \n"
+ "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
+ "# The value 0x14 disables this mechanism\n"
+ "head_of_queue_lifetime 0x%02x\n\n"
+ "# The maximal time a packet can wait at the head of queue on \n"
+ "# switch port connected to a HCA\n"
+ "leaf_head_of_queue_lifetime 0x%02x\n\n"
+ "# Limit the maximal operational VLs\n"
+ "max_op_vls %u\n\n"
+ "# The subnet_timeout code that will be set for all the ports\n"
+ "# The actual timeout is 4.096usec * 2^<subnet_timeout code>\n"
+ "subnet_timeout %u\n\n"
+ "# Threshold of local phy errors for sending Trap 129\n"
+ "local_phy_errors_threshold 0x%02x\n\n"
+ "# Threshold of credits over-run errors for sending Trap 129\n"
+ "overrun_errors_threshold 0x%02x\n\n",
+ cl_ntoh64(p_opts->m_key),
+ cl_ntoh16(p_opts->m_key_lease_period),
+ cl_ntoh64(p_opts->sm_key),
+ cl_ntoh64(p_opts->subnet_prefix),
+ p_opts->lmc,
+ p_opts->packet_life_time,
+ p_opts->head_of_queue_lifetime,
+ p_opts->leaf_head_of_queue_lifetime,
+ p_opts->max_op_vls,
+ p_opts->subnet_timeout,
+ p_opts->local_phy_errors_threshold,
+ p_opts->overrun_errors_threshold
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# SWEEP OPTIONS\n#\n"
+ "# The number of seconds between subnet sweeps (0 disables it)\n"
+ "sweep_interval %u\n\n"
+ "# If TRUE cause all lids to be re-assigned\n"
+ "reassign_lids %s\n\n"
+ "# If TRUE ignore existing LFT entries on first sweep (default).\n"
+ "# Otherwise only non minimal hop cases are modified.\n"
+ "# NOTE: A standby SM clears its first sweep flag - since the\n"
+ "# master SM already sweeps...\n"
+ "reassign_lfts %s\n\n"
+ "# If true forces every sweep to be a heavy sweep\n"
+ "force_heavy_sweep %s\n\n"
+ "# If true every trap will cause a heavy sweep.\n"
+ "# NOTE: successive same traps (>10) are supressed\n"
+ "sweep_on_trap %s\n\n",
+ p_opts->sweep_interval,
+ p_opts->reassign_lids ? "TRUE" : "FALSE",
+ p_opts->reassign_lfts ? "TRUE" : "FALSE",
+ p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
+ p_opts->sweep_on_trap ? "TRUE" : "FALSE"
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# ROUTING OPTIONS\n#\n"
+ "# If true do not count switches as link subscriptions\n"
+ "port_profile_switch_nodes %s\n\n"
+ "# Activate the Up/Down routing algorithm\n"
+ "updn_activate %s\n\n",
+ p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE",
+ p_opts->updn_activate ? "TRUE" : "FALSE"
+ );
+ if (p_opts->updn_guid_file)
+ fprintf( opts_file,
+ "# The file holding the Up/Down root node guids\n"
+ "# One guid in each line\n"
+ "updn_guid_file %s\n\n",
+ p_opts->updn_guid_file);
+
+ fprintf(
+ opts_file,
+ "#\n# HANDOVER - MULTIPLE SM's OPTIONS\n#\n"
+ "# SM priority used for deciding who is the master\n"
+ "sm_priority %u\n\n"
+ "# If TRUE other SM's on the subnet should be ignored\n"
+ "ignore_other_sm %s\n\n"
+ "# Timeout in [sec] between two polls of active master SM\n"
+ "sminfo_polling_timeout %u\n\n"
+ "# Number of failing polls of remote SM that declares it dead\n"
+ "polling_retry_number %u\n\n",
+ p_opts->sm_priority,
+ p_opts->ignore_other_sm ? "TRUE" : "FALSE",
+ p_opts->sminfo_polling_timeout,
+ p_opts->polling_retry_number
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# TIMING AND THREADING OPTIONS\n#\n"
+ "# Number of MADs sent in parallel\n"
+ "max_wire_smps %u\n\n"
+ "# The time taken to a transaction to finish in [msec]\n"
+ "transaction_timeout %u\n\n"
+ "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
+ "# If there is more then one message in the queue and the last message\n"
+ "# stayed in the queue more then this value any SA request will be \n"
+ "# immediatly returned with a BUSY status.\n"
+ "max_msg_fifo_timeout %u\n\n"
+ "# Use a single thread for handling SA queries\n"
+ "single_thread %s\n\n",
+ p_opts->max_wire_smps,
+ p_opts->transaction_timeout,
+ p_opts->max_msg_fifo_timeout,
+ p_opts->single_thread ? "TRUE" : "FALSE"
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# DEBUG FEATURES\n#\n"
+ "# The log flags used\n"
+ "log_flags 0x%02x\n\n"
+ "# Force flush of the log file after each log message\n"
+ "force_log_flush %s\n\n"
+ "# Log file to be used\n"
+ "log_file %s\n\n"
+ "# The directory to hold the file OpenSM dumps\n"
+ "dump_files_dir %s\n\n"
+ "# If TRUE if OpenSM should disable multicast support\n"
+ "no_multicast_option %s\n\n"
+ "# No multicast routing is performed if TRUE\n"
+ "disable_multicast %s\n\n",
+ p_opts->log_flags,
+ p_opts->force_log_flush ? "TRUE" : "FALSE",
+ p_opts->log_file,
+ p_opts->dump_files_dir,
+ p_opts->no_multicast_option ? "TRUE" : "FALSE",
+ p_opts->disable_multicast ? "TRUE" : "FALSE"
+ );
+
+ /* optional string attributes ... */
+
+ fclose(opts_file);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_si_rcv_clear_sc_bit(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN ib_switch_info_t* const p_si )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_api_status_t status;
+ osm_madw_context_t context;
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_clear_sc_bit );
+
+ context.si_context.node_guid = osm_node_get_node_guid( p_node );
+ context.si_context.set_method = TRUE;
+ context.si_context.light_sweep = FALSE;
+
+ cl_memcpy( payload, p_si, IB_SMP_DATA_SIZE );
+
+ status = osm_req_set( p_rcv->p_req,
+ osm_node_get_any_dr_path_ptr( p_node ),
+ payload,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_clear_sc_bit: ERR 3601: "
+ "Unable to clear state change bit for switch "
+ "with GUID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_si_rcv_get_port_info(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_madw_context_t context;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ uint8_t num_ports;
+ osm_dr_path_t dr_path;
+ const ib_smp_t* p_smp;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_port_info );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ /*
+ Request PortInfo attribute for each port on the switch.
+ Don't trust the port's own DR Path, since it may no longer
+ be a legitimate path through the subnet.
+ Build a path from the mad instead, since we know that path works.
+ The port's DR Path info gets updated when the PortInfo
+ attribute is received.
+ */
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+ context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+ context.pi_context.set_method = FALSE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ num_ports = osm_node_get_num_physp( p_node );
+ osm_dr_path_init( &dr_path,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count, p_smp->initial_path );
+
+ for( port_num = 0; port_num < num_ports; port_num++)
+ {
+ status = osm_req_get(
+ p_rcv->p_req,
+ &dr_path,
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_port_info: ERR 3602: "
+ "Failure initiating PortInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_si_rcv_get_fwd_tbl(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw )
+{
+ osm_madw_context_t context;
+ osm_dr_path_t *p_dr_path;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ uint32_t block_id_ho;
+ uint32_t max_block_id_ho;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_fwd_tbl );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ context.lft_context.node_guid = osm_node_get_node_guid( p_node );
+ context.lft_context.set_method = FALSE;
+
+ max_block_id_ho = osm_switch_get_max_block_id_in_use( p_sw );
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+ for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_fwd_tbl: "
+ "Retrieving FT block %u.\n", block_id_ho );
+ }
+
+ status = osm_req_get(
+ p_rcv->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_LIN_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_fwd_tbl: ERR 3603: "
+ "Failure initiating PortInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_si_rcv_get_mcast_fwd_tbl(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw )
+{
+ osm_madw_context_t context;
+ osm_dr_path_t *p_dr_path;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ osm_mcast_tbl_t* p_tbl;
+ uint32_t block_id_ho;
+ uint32_t max_block_id_ho;
+ uint32_t position;
+ uint32_t max_position;
+ uint32_t attr_mod_ho;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_mcast_fwd_tbl );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_switch_get_mcast_fwd_tbl_size( p_sw ) == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Multicast not supported by switch 0x%016" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ goto Exit;
+ }
+
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+ context.mft_context.set_method = FALSE;
+
+ max_block_id_ho = osm_mcast_tbl_get_max_block( p_tbl );
+
+ if( max_block_id_ho > IB_MCAST_MAX_BLOCK_ID )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3609: "
+ "Out-of-range mcast block size = %u on switch 0x%016" PRIx64
+ ".\n", max_block_id_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ goto Exit;
+ }
+
+ max_position = osm_mcast_tbl_get_max_position( p_tbl );
+
+ CL_ASSERT( max_position <= IB_MCAST_POSITION_MAX );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Max MFT block = %u, Max position = %u.\n", max_block_id_ho,
+ max_position );
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+ for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Retrieving MFT block %u.\n", block_id_ho );
+ }
+
+ for( position = 0; position <= max_position; position++ )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Retrieving MFT position %u.\n", position );
+ }
+
+ attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT;
+ status = osm_req_get(
+ p_rcv->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_MCAST_FWD_TBL,
+ cl_hton32( attr_mod_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3607: "
+ "Failure initiating PortInfo request (%s).\n",
+ ib_get_err_str(status));
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Lock must be held on entry to this function.
+**********************************************************************/
+void
+__osm_si_rcv_process_new(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_switch_t *p_sw;
+ osm_switch_t *p_check;
+ ib_switch_info_t *p_si;
+ ib_smp_t *p_smp;
+ cl_qmap_t *p_sw_guid_tbl;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+
+ /*
+ Allocate a new switch object for this switch,
+ and place it in the switch table.
+ */
+ p_sw = osm_switch_new( p_node, p_madw );
+ if( p_sw == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_process_new: ERR 3608: "
+ "Unable to allocate new switch object.\n" );
+ goto Exit;
+ }
+
+ /* set subnet max mlid to the minimum MulticastFDBCap of all switches */
+ if ( p_sw->mcast_tbl.max_mlid_ho < p_rcv->p_subn->max_multicast_lid_ho )
+ {
+ p_rcv->p_subn->max_multicast_lid_ho = p_sw->mcast_tbl.max_mlid_ho;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_new: "
+ "Subnet max multicast lid is 0x%X\n",
+ p_rcv->p_subn->max_multicast_lid_ho );
+ }
+
+ /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */
+ if ( p_sw->fwd_tbl.p_lin_tbl->size < p_rcv->p_subn->max_unicast_lid_ho )
+ {
+ p_rcv->p_subn->max_unicast_lid_ho = p_sw->fwd_tbl.p_lin_tbl->size;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_new: "
+ "Subnet max unicast lid is 0x%X\n",
+ p_rcv->p_subn->max_unicast_lid_ho );
+ }
+
+ p_check = (osm_switch_t*)cl_qmap_insert( p_sw_guid_tbl,
+ osm_node_get_node_guid( p_node ), &p_sw->map_item );
+
+ if( p_check != p_sw )
+ {
+ /*
+ This shouldn't happen since we hold the lock!
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_process_new: ERR 3605: "
+ "Unable to add new switch object to database.\n" );
+ osm_switch_delete( &p_sw );
+ goto Exit;
+ }
+
+ /*
+ Update the switch info according to the
+ info we just received.
+ */
+ osm_switch_set_switch_info( p_sw, p_si );
+ osm_switch_discovery_count_inc( p_sw );
+
+ /*
+ Get the PortInfo attribute for every port.
+ */
+ __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+ __osm_si_rcv_get_fwd_tbl( p_rcv, p_sw );
+
+ /*
+ Don't bother retrieving the current multicast tables
+ from the switches. The current version of SM does
+ not support silent take-over of an existing multicast
+ configuration.
+
+ Gathering the multicast tables can also generate large amounts
+ of extra subnet-init traffic.
+
+ The code to retrieve the tables was fully debugged.
+ */
+#if 0
+ if( !p_rcv->p_subn->opt.disable_multicast )
+ __osm_si_rcv_get_mcast_fwd_tbl( p_rcv, p_sw );
+#endif
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Lock must be held on entry to this function.
+ Return 1 if the caller is expected to send a change_detected event.
+ this can not be done internally as the event needs the lock...
+**********************************************************************/
+boolean_t
+__osm_si_rcv_process_existing(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_switch_t* const p_sw,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_switch_info_t *p_si;
+ osm_si_context_t *p_si_context;
+ ib_smp_t *p_smp;
+ boolean_t is_change_detected = FALSE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_existing );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+ p_si_context = osm_madw_get_si_context_ptr( p_madw );
+
+ if( p_si_context->set_method )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Received logical SetResp().\n" );
+ }
+
+ osm_switch_set_switch_info( p_sw, p_si );
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Received logical GetResp().\n" );
+ }
+
+ osm_switch_set_switch_info( p_sw, p_si );
+
+ /*
+ Check the port state change bit. If true, then this switch
+ has seen a port state transition, so continue probing.
+ */
+ if( p_si_context->light_sweep == TRUE )
+ {
+ /* This is a light sweep */
+ /* If the mad was returned with an error -
+ signal a change to the state manager. */
+ if ( ib_smp_get_status( p_smp ) != 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_existing: "
+ "GetResp() received with error in light sweep. "
+ "Commencing heavy sweep.\n" );
+ is_change_detected = TRUE;
+ }
+ else
+ {
+ /*
+ If something changed, then just signal the state
+ manager. Don't attempt to probe further during
+ a light sweep.
+ */
+ if( ib_switch_info_get_state_change( p_si ) )
+ {
+ osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+ is_change_detected = TRUE;
+ }
+ }
+ }
+ else
+ {
+ /*
+ This is a heavy sweep. Get information regardless
+ of the state change bit.
+ */
+ osm_switch_discovery_count_inc( p_sw );
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_existing: "
+ "discovery_count is:%u \n",
+ osm_switch_discovery_count_get( p_sw ) );
+
+ /* If this is the first discovery - then get the port_info */
+ if ( osm_switch_discovery_count_get( p_sw ) == 1 )
+ __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Not discovering again through switch:0x%"
+ PRIx64 ".\n",
+ osm_node_get_node_guid( p_sw->p_node) );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return is_change_detected;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_construct(
+ IN osm_si_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_destroy(
+ IN osm_si_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_init(
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_si_rcv_init );
+
+ osm_si_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_process(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_node_guid_tbl;
+ cl_qmap_t *p_sw_guid_tbl;
+ ib_switch_info_t *p_si;
+ ib_smp_t *p_smp;
+ osm_node_t *p_node;
+ osm_switch_t *p_sw;
+ ib_net64_t node_guid;
+ osm_si_context_t *p_context;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ /*
+ Acquire the switch object and add the switch info.
+ */
+
+ p_context = osm_madw_get_si_context_ptr( p_madw );
+
+ node_guid = p_context->node_guid;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_si_rcv_process: "
+ "Switch GUID = 0x%016" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+ p_node = (osm_node_t*)cl_qmap_get( p_node_guid_tbl, node_guid );
+ if( p_node == (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_process: ERR 3606: "
+ "SwitchInfo received for nonexistent node "
+ "with GUID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+
+ /*
+ Hack for bad value in Mellanox switch
+ */
+ if( cl_ntoh16( p_si->lin_top ) > IB_LID_UCAST_END_HO )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_process: ERR 3610: "
+ "\n\t\t\t\tBad LinearFDBTop value = 0x%X "
+ "on switch 0x%" PRIx64 "."
+ "\n\t\t\t\tForcing correction to 0x%X.\n",
+ cl_ntoh16( p_si->lin_top ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ 0 );
+
+ p_si->lin_top = 0;
+ }
+
+ /*
+ Acquire the switch object for this switch.
+ */
+ p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl,
+ node_guid );
+ if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+ {
+ __osm_si_rcv_process_new( p_rcv, p_node, p_madw );
+ /*
+ A new switch was found during the sweep so we need
+ to ignore the current LFT settings.
+ */
+ p_rcv->p_subn->ignore_existing_lfts = TRUE;
+ }
+ else
+ {
+ /* we might get back a request for signaling change was detected */
+ if (__osm_si_rcv_process_existing( p_rcv, p_node, p_sw, p_madw ))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ OSM_SIGNAL_CHANGE_DETECTED );
+ goto Exit;
+ }
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_si_rcv_ctrl_t.
+ * This object represents the SwitchInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_si_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_si_rcv_process( ((osm_si_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_construct(
+ IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_destroy(
+ IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_ctrl_init(
+ IN osm_si_rcv_ctrl_t* const p_ctrl,
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_si_rcv_ctrl_init );
+
+ osm_si_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SWITCH_INFO,
+ __osm_si_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_ctrl_init: ERR 3701: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sweep_fail_ctrl_t.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sweep_fail_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ osm_sweep_fail_ctrl_t* const p_ctrl = (osm_sweep_fail_ctrl_t*)context;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sweep_fail_ctrl_disp_callback );
+
+ UNUSED_PARAM( p_data );
+ /*
+ Notify the state manager that we had a light sweep failure.
+ */
+ osm_state_mgr_process( p_ctrl->p_state_mgr,
+ OSM_SIGNAL_LIGHT_SWEEP_FAIL );
+
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_construct(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_destroy(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sweep_fail_ctrl_init );
+
+ osm_sweep_fail_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_state_mgr = p_state_mgr;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_LIGHT_SWEEP_FAIL,
+ __osm_sweep_fail_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sweep_fail_ctrl_init: ERR 3501: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_switch_t.
+ * This object represents an Infiniband switch.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_switch.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_construct(
+ IN osm_switch_t* const p_sw )
+{
+ CL_ASSERT( p_sw );
+ cl_memclr( p_sw, sizeof(*p_sw) );
+ osm_lid_matrix_construct( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_switch_init(
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ ib_switch_info_t *p_si;
+ ib_smp_t *p_smp;
+ uint8_t num_ports;
+ uint32_t port_num;
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_madw );
+ CL_ASSERT( p_node );
+
+ osm_switch_construct( p_sw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+ num_ports = osm_node_get_num_physp( p_node );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO );
+
+ p_sw->p_node = p_node;
+ p_sw->switch_info = *p_si;
+
+ status = osm_lid_matrix_init( &p_sw->lmx, num_ports );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_fwd_tbl_init( &p_sw->fwd_tbl, p_si );
+
+ p_sw->p_pro = cl_zalloc( sizeof(*p_sw->p_pro) * num_ports );
+ if( p_sw->p_pro == NULL )
+ {
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ status = osm_mcast_tbl_init( &p_sw->mcast_tbl,
+ osm_node_get_num_physp( p_node ), cl_ntoh16( p_si->mcast_cap ) );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ osm_port_pro_construct( &p_sw->p_pro[port_num] );
+
+ Exit:
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_destroy(
+ IN osm_switch_t* const p_sw )
+{
+ /* free memory to avoid leaks */
+ osm_mcast_tbl_destroy( &p_sw->mcast_tbl );
+ cl_free( p_sw->p_pro );
+ osm_fwd_tbl_destroy( &p_sw->fwd_tbl );
+ osm_lid_matrix_destroy( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_delete(
+ IN OUT osm_switch_t** const pp_sw )
+{
+ osm_switch_destroy( *pp_sw );
+ cl_free( *pp_sw );
+ *pp_sw = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t*
+osm_switch_new(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status;
+ osm_switch_t *p_sw;
+
+ p_sw = (osm_switch_t*)cl_zalloc( sizeof(*p_sw) );
+ if( p_sw )
+ {
+ status = osm_switch_init( p_sw, p_node, p_madw );
+ if( status != IB_SUCCESS )
+ osm_switch_delete( &p_sw );
+ }
+
+ return( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t block_id,
+ OUT uint8_t* const p_block )
+{
+ uint16_t base_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint16_t block_top_lid_ho;
+ uint32_t lids_per_block;
+ osm_fwd_tbl_t *p_tbl;
+ boolean_t return_flag = FALSE;
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_block );
+
+ p_tbl = osm_switch_get_fwd_tbl_ptr( p_sw );
+ max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+ lids_per_block = osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl );
+ base_lid_ho = (uint16_t)(block_id * lids_per_block);
+
+ if( base_lid_ho < max_lid_ho )
+ {
+ cl_memclr( p_block, IB_SMP_DATA_SIZE );
+ /*
+ Determine the range of LIDs we can return with this block.
+ */
+ block_top_lid_ho = (uint16_t)(base_lid_ho + lids_per_block - 1);
+ if( block_top_lid_ho > max_lid_ho )
+ block_top_lid_ho = max_lid_ho;
+
+ /*
+ Configure the forwarding table with the routing
+ information for the specified block of LIDs.
+ */
+ for( lid_ho = base_lid_ho; lid_ho <= block_top_lid_ho; lid_ho++ )
+ {
+ p_block[lid_ho - base_lid_ho] = osm_fwd_tbl_get( p_tbl, lid_ho );
+ }
+
+ return_flag = TRUE;
+ }
+
+ return( return_flag );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_path(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const boolean_t ignore_existing,
+ IN OUT uint64_t *remote_sys_guids,
+ IN OUT uint16_t *p_num_used_sys,
+ IN OUT uint64_t *remote_node_guids,
+ IN OUT uint16_t *p_num_used_nodes,
+ IN const uint32_t max_routes_subscribed,
+ IN boolean_t ui_ucast_fdb_assign_func_defined
+ )
+{
+ /*
+ We support an enhanced LMC aware routing mode:
+ In case of LMC > 0 we can track the remote side
+ system and node for all of the lids of the target
+ and try and avoid routing again through the same
+ system / node.
+
+ If the procedure is provided with the tracking arrays
+ and counters we can conduct this algorithm.
+ */
+ boolean_t routing_for_lmc = remote_sys_guids && remote_node_guids &&
+ p_num_used_sys && p_num_used_nodes;
+ boolean_t sys_used, node_used;
+ uint16_t i;
+ uint8_t hops;
+ uint8_t least_hops;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint32_t least_paths = 0xFFFFFFFF;
+ /*
+ The follwing will track the least paths if the
+ route should go through a new system/node
+ */
+ uint32_t least_paths_other_sys = 0xFFFFFFFF;
+ uint32_t least_paths_other_nodes = 0xFFFFFFFF;
+ uint32_t check_count;
+ uint8_t best_port = 0;
+ /*
+ These vars track the best port if it connects to
+ not used system/node.
+ */
+ uint8_t best_port_other_sys = 0;
+ uint8_t best_port_other_node = 0;
+ boolean_t port_found = FALSE;
+ osm_physp_t *p_physp;
+ osm_physp_t *p_rem_physp;
+ osm_node_t *p_rem_node;
+
+ CL_ASSERT( lid_ho > 0 );
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+
+ least_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+
+ if ( least_hops == OSM_NO_PATH )
+ return (OSM_NO_PATH);
+
+ /*
+ First, enquire with the forwarding table for an existing
+ route. If one is found, honor it unless:
+ 1. the ignore existing flag is set.
+ 2. the physical port is not a valid one or not healthy
+ 3. the physical port has a remote port (the link is up)
+ 4. the port has min-hops to the target (avoid loops)
+ */
+ if( !ignore_existing )
+ {
+ port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho );
+
+ if (port_num != OSM_NO_PATH)
+ {
+ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+ /*
+ Don't be too trusting of the current forwarding table!
+ Verify that the port number is legal and that the
+ LID is reachable through this port.
+ */
+ if( (port_num < num_ports ) &&
+ osm_physp_is_valid(p_physp) &&
+ osm_physp_is_healthy(p_physp) &&
+ osm_physp_get_remote(p_physp) )
+ {
+ hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+ /*
+ If we aren't using pre-defined user routes function, then
+ we need to make sure that the current path is the minimum one.
+ In case of having such a user function - this check will not
+ be done, and the old routing will be used.
+ Note: This means that it is the user's job to clean all data
+ in the forwarding tables that he wants to be overridden by the
+ minimum hop function.
+ */
+ if ( hops == least_hops || ui_ucast_fdb_assign_func_defined )
+ {
+ return( port_num );
+ }
+ }
+ }
+ }
+
+ /*
+ This algorithm selects a port based on a static load balanced
+ selection across equal hop-count ports.
+ There is lots of room for improved sophistication here,
+ possibly guided by user configuration info.
+ */
+
+ /*
+ OpenSM routing is "local" - not considering a full lid to lid
+ path. As such we can not guarantee a path will not loop if we
+ do not always follow least hops.
+ So we must abort if not least hops.
+ */
+
+ /* port number starts with zero and num_ports is 1 + num phys ports */
+ for ( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ if ( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops)
+ {
+ /* let us make sure it is not down or un-healthy */
+ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+ if (osm_physp_is_valid(p_physp) &&
+ osm_physp_is_healthy(p_physp) &&
+ /*
+ we require all - non sma ports to be linked
+ to be routed through
+ */
+ (! port_num || osm_physp_get_remote(p_physp)))
+ {
+
+ /*
+ We located a least-hop port, possibly one of many.
+ For this port, check the running total count of
+ the number of paths through this port. Select
+ the port routing the least number of paths.
+ */
+ check_count = osm_port_pro_path_count_get(
+ &p_sw->p_pro[port_num] );
+
+ /*
+ Advanced LMC routing requires tracking of the
+ best port by the node connected to the other side of
+ it .
+ */
+ if (routing_for_lmc && port_num)
+ {
+ /* printf("LID:%u SYS:%d NODE:%d\n", lid_ho,*p_num_used_sys, *p_num_used_nodes); */
+
+ /* Get the Remote Node */
+ p_rem_physp = osm_physp_get_remote(p_physp);
+ p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+ /* Is the sys guid already used ? */
+ sys_used = FALSE;
+ for (i = 0; !sys_used && (i < *p_num_used_sys); i++)
+ if (!cl_memcmp(&p_rem_node->node_info.sys_guid,
+ &remote_sys_guids[i],
+ sizeof(uint64_t)))
+ sys_used = TRUE;
+
+ /* If not update the least hops for this case */
+ if (! sys_used)
+ {
+ if (check_count < least_paths_other_sys)
+ {
+ least_paths_other_sys = check_count;
+ best_port_other_sys = port_num;
+ }
+ }
+ else
+ { /* same sys found - try node */
+
+ /* Else Is the node guid already used ? */
+ node_used = FALSE;
+ for (i = 0; !node_used && (i < *p_num_used_nodes); i++)
+ if (!cl_memcmp(&p_rem_node->node_info.node_guid,
+ &remote_node_guids[i],
+ sizeof(uint64_t)))
+ node_used = TRUE;
+
+
+ /* If not update the least hops for this case */
+ if (! node_used)
+ {
+ if (check_count < least_paths_other_nodes)
+ {
+ least_paths_other_nodes = check_count;
+ best_port_other_node = port_num;
+ }
+ }
+
+ } /* same sys found */
+ } /* routing for LMC mode */
+
+ /*
+ the count is min but also lower then the max subscribed
+ */
+ if( (check_count < least_paths) &&
+ (check_count <= max_routes_subscribed))
+ {
+ port_found = TRUE;
+ best_port = port_num;
+ least_paths = check_count;
+ }
+ }
+ }
+ }
+
+ if ( port_found == FALSE )
+ return (OSM_NO_PATH);
+
+ /*
+ if we are in enhanced routing mode and the best port is not
+ the local port 0
+ */
+ if (routing_for_lmc && best_port)
+ {
+ /* Select the least hop port of the non used sys first */
+ if (best_port_other_sys)
+ best_port = best_port_other_sys;
+ else if (best_port_other_node)
+ best_port = best_port_other_node;
+
+ /* track the remote node and system of the port used. */
+ p_physp = osm_node_get_physp_ptr(p_sw->p_node, best_port);
+ p_rem_physp = osm_physp_get_remote(p_physp);
+ p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+ cl_memcpy(&remote_node_guids[*p_num_used_nodes],
+ &(p_rem_node->node_info.node_guid),
+ sizeof(uint64_t));
+ (*p_num_used_nodes)++;
+ cl_memcpy(&remote_sys_guids[*p_num_used_sys],
+ &(p_rem_node->node_info.sys_guid),
+ sizeof(uint64_t));
+ (*p_num_used_sys)++;
+ }
+
+ return( best_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_prepare_path_rebuild(
+ IN osm_switch_t* const p_sw )
+{
+ uint8_t port_num;
+ uint8_t num_ports;
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+ osm_lid_matrix_clear( &p_sw->lmx );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ osm_port_pro_construct( &p_sw->p_pro[port_num] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_mcast_path(
+ IN osm_switch_t* const p_sw,
+ IN uint16_t const lid_ho,
+ IN uint16_t const mlid_ho,
+ IN boolean_t const ignore_existing )
+{
+ uint8_t hops;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint8_t least_hops;
+
+ CL_ASSERT( lid_ho > 0 );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+ num_ports = osm_switch_get_num_ports( p_sw );
+
+ /*
+ If the user wants us to ignore existing multicast routes,
+ then simply return the shortest hop count path to the
+ target port.
+
+ Otherwise, return the first port that has a path to the target,
+ picking from the ports that are already in the multicast group.
+ */
+ if( !ignore_existing )
+ {
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ if( osm_mcast_tbl_is_port( &p_sw->mcast_tbl, mlid_ho, port_num ) )
+ {
+ /*
+ Don't be too trusting of the current forwarding table!
+ Verify that the LID is reachable through this port.
+ */
+ hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+ if( hops != OSM_NO_PATH )
+ {
+ return( port_num );
+ }
+ }
+ }
+ }
+
+ /*
+ Either no existing mcast paths reach this port or we are
+ ignoring existing paths.
+
+ Determine the best multicast path to the target. Note that this
+ algorithm is slightly different from the one used for unicast route
+ recommendation. In this case (multicast) we must NOT
+ perform any sort of load balancing. We MUST take the FIRST
+ port found that has <= the lowest hop count path. This prevents
+ more than one multicast path to the same remote switch which
+ prevents a multicast loop. Multicast loops are bad since the same
+ multicast packet will go around and around, inevitably creating
+ a black hole that will destroy the Earth in a firey conflagration.
+ */
+ least_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ if( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops )
+ break;
+ }
+
+ CL_ASSERT( port_num < num_ports );
+ return( port_num );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ *
+ * TRAP HANDLING:
+ *
+ * Assuming traps can be caused by bad hardware we should provide
+ * a mechanism for filtering their propagation into the actual logic
+ * of OpenSM such that it is not overloaded by them.
+ *
+ * We will provide a trap filtering mechanism with "Aging" capability.
+ * This mechanism will track incoming traps, clasify them by their
+ * source and content and provide back their age.
+ *
+ * A timer running in the background will toggle a timer counter
+ * that should be referenced by the aging algorithm.
+ * To provide an efficient handling of aging. We also track all traps
+ * in a sorted list by their aging.
+ *
+ * The generic Aging Tracker mechanism is implemented in the
+ * cl_aging_tracker object.
+ *
+ **********************************************************************/
+
+typedef struct _osm_trap_aging_tracker_context
+{
+ osm_log_t* p_log;
+ osm_physp_t* p_physp;
+} osm_trap_aging_tracker_context_t;
+
+/**********************************************************************
+ **********************************************************************/
+osm_physp_t *
+__get_physp_by_lid_and_num(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN uint16_t lid,
+ IN uint8_t num)
+{
+ cl_ptr_vector_t *p_vec = &(p_rcv->p_subn->port_lid_tbl);
+ osm_port_t *p_port;
+
+ if (lid > cl_ptr_vector_get_size(p_vec))
+ return NULL;
+
+ p_port = (osm_port_t *)cl_ptr_vector_get(p_vec, lid);
+ if (! p_port)
+ return NULL;
+
+ if (osm_port_get_num_physp(p_port) < num)
+ return NULL;
+
+ return( osm_port_get_phys_ptr(p_port, num) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+ IN uint64_t key,
+ IN uint32_t num_regs,
+ IN void* context )
+{
+ osm_trap_rcv_t* p_rcv = (osm_trap_rcv_t*)context;
+ uint16_t lid;
+ uint8_t port_num;
+ osm_physp_t* p_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_aging_tracker_callback );
+
+ if (osm_exit_flag)
+ /* We got an exit flag - do nothing */
+ return 0;
+
+ lid = cl_ntoh16((uint16_t)(( key & 0x0000FFFF00000000ULL) >> 32));
+ port_num = (uint8_t)(( key & 0x00FF000000000000ULL) >> 48);
+
+ p_physp = __get_physp_by_lid_and_num( p_rcv, lid, port_num );
+
+ if (!p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_trap_rcv_aging_tracker_callback: "
+ "Cannot find port num:%u with lid:%u\n",
+ port_num, lid );
+ }
+ else
+ {
+ /* make sure the physp is still valid */
+ if ( osm_physp_is_valid(p_physp) )
+ {
+ /* If the health port was false - set it to true */
+ if (!osm_physp_is_healthy(p_physp) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_trap_rcv_aging_tracker_callback: "
+ "Clearing health bit of port num:%u with lid:%u\n",
+ port_num, lid );
+
+ /* Clear its health bit */
+ osm_physp_set_health(p_physp, TRUE);
+ }
+ }
+ }
+
+ OSM_LOG_EXIT (p_rcv->p_log );
+
+ /* We want to remove the event from the tracker - so
+ need to return zero. */
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_construct(
+ IN osm_trap_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+ cl_event_wheel_construct( &p_rcv->trap_aging_tracker );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_destroy(
+ IN osm_trap_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+
+ cl_event_wheel_destroy( &p_rcv->trap_aging_tracker );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_init(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_trap_rcv_init );
+
+ osm_trap_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ cl_event_wheel_init( &p_rcv->trap_aging_tracker, p_log );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ * CRC calculation for notice identification
+ **********************************************************************/
+
+#define CRC32_POLYNOMIAL 0xEDB88320L
+
+/* calculate the crc for a given buffer */
+uint32_t
+__osm_trap_calc_crc32(void *buffer, uint32_t count)
+{
+ uint32_t temp1, temp2;
+ uint32_t crc = -1L;
+ unsigned char *p = (unsigned char *)buffer;
+ /* pre - calculated table for faster crc calculation */
+ static uint32_t crc_table[256];
+ static boolean_t first = TRUE;
+ int i, j;
+
+ /* if we need to initialize the lookup table */
+ if (first)
+ {
+ /* calc the CRC table */
+ for (i = 0; i <= 255; i++)
+ {
+ crc = i;
+ for (j = 8; j > 0; j--)
+ if (crc & 1)
+ crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
+ else
+ crc >>= 1;
+ crc_table[i] = crc;
+ }
+ first = FALSE;
+ }
+
+ crc = -1L;
+ /* do the calculation */
+ while (count-- != 0)
+ {
+ temp1 = (crc >> 8) & 0x00FFFFFFL;
+ temp2 = crc_table[((int)crc ^ *p++) & 0xFF];
+ crc = temp1 ^ temp2;
+ }
+ return crc;
+}
+
+
+/********************************************************************
+ ********************************************************************/
+
+/* The key is created in the following manner:
+ port_num lid crc
+ \______/ \___/ \___/
+ 16b 16b 32b
+*/
+void
+__osm_trap_get_key(
+ IN uint16_t lid,
+ IN uint8_t port_num,
+ IN ib_mad_notice_attr_t* p_ntci,
+ OUT uint64_t *trap_key)
+{
+ uint32_t crc = 0;
+
+ CL_ASSERT(trap_key);
+
+ crc = __osm_trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t));
+ *trap_key = ((uint64_t)port_num << 48) | ((uint64_t)lid << 32) | crc;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_trap_rcv_process_request(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ uint8_t payload[sizeof(ib_mad_notice_attr_t)];
+ ib_smp_t* p_smp;
+ ib_mad_notice_attr_t* p_ntci = (ib_mad_notice_attr_t*)payload;
+ ib_api_status_t status;
+ osm_madw_t tmp_madw; /* we need a copy to last after */
+ /* repress. */
+ uint64_t trap_key;
+ uint32_t num_received;
+ osm_physp_t* p_physp;
+ cl_ptr_vector_t* p_tbl;
+ osm_port_t* p_port;
+ ib_net16_t source_lid = 0;
+ boolean_t is_gsi = TRUE;
+ uint8_t port_num = 0;
+ boolean_t physp_change_trap = FALSE;
+ uint64_t event_wheel_timeout = OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT;
+ boolean_t run_heavy_sweep = FALSE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_request );
+
+ CL_ASSERT( p_madw );
+
+ if (osm_exit_flag)
+ {
+ /*
+ We got an exit flag - do nothing
+ Otherwise we start a sweep on the trap 144 caused by cleaning up
+ SM Cap bit ...
+ */
+ goto Exit;
+ }
+
+ /* update the is_gsi flag according to the mgmt_class field */
+ if (p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
+ p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_DIR )
+ is_gsi = FALSE;
+
+ /*
+ No real need to grab the lock for this function.
+ */
+ cl_memclr( payload, sizeof( payload ) );
+ cl_memclr( &tmp_madw, sizeof( tmp_madw ));
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( p_smp->method != IB_MAD_METHOD_TRAP )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3801: "
+ "Unsupported method 0x%X.\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ /*
+ * The NOTICE Attribute is part of the SMP CLASS attributes
+ * As such the actual attribute data resides inside the SMP
+ * payload.
+ */
+
+ cl_memcpy(payload, &(p_smp->data), IB_SMP_DATA_SIZE);
+ cl_memcpy(&tmp_madw, p_madw, sizeof( tmp_madw ));
+
+ if (is_gsi == FALSE)
+ {
+ /* We are in smi flow */
+ /*
+ * When we received a TRAP with dlid = 0 - it means it
+ * came from our own node. So we need to fix it.
+ */
+
+ if (p_madw->mad_addr.addr_type.smi.source_lid == 0)
+ {
+ /* Check if the sm_base_lid is 0. If yes - this means that
+ the local lid wasn't configured yet. Don't send a response
+ to the trap. */
+ if (p_rcv->p_subn->sm_base_lid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_trap_rcv_process_request: "
+ "Received a SLID=0 Trap. local LID=0. Ignoring mad. \n");
+ goto Exit;
+ }
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_trap_rcv_process_request: "
+ "Received a SLID=0 Trap. Using local LID:0x%04X instead:.\n",
+ cl_ntoh16(p_rcv->p_subn->sm_base_lid)
+ );
+ tmp_madw.mad_addr.addr_type.smi.source_lid = p_rcv->p_subn->sm_base_lid;
+ }
+
+ source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid;
+
+ /* Print some info about the incoming Trap */
+ if (ib_notice_is_generic(p_ntci))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: "
+ "Received Generic Notice type:0x%02X num:%u Producer:%u "
+ "from LID:0x%04X TID:0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntci),
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+ cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+ cl_hton16(source_lid),
+ cl_ntoh64(p_smp->trans_id)
+ );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: "
+ "Received Vend Notice type:0x%02X vend:0x%06X dev:%u "
+ "from LID:0x%04X TID:0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntci),
+ cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
+ cl_ntoh16(p_ntci->g_or_v.vend.dev_id),
+ cl_ntoh16(source_lid),
+ cl_ntoh64(p_smp->trans_id)
+ );
+ }
+ }
+
+ osm_dump_notice( p_rcv->p_log ,p_ntci, OSM_LOG_VERBOSE);
+
+ status = osm_resp_send( p_rcv->p_resp, &tmp_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3802: "
+ "Error sending response (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * We would like to filter out recurring Traps so we track them by
+ * their source lid and content. If the same trap was already
+ * received within the aging time window more than 10 times,
+ * we simply ignore it. This is done only if we are in smi mode
+ */
+
+ if (is_gsi == FALSE)
+ {
+ if (ib_notice_is_generic(p_ntci) &&
+ ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131))) )
+ {
+ /* If this is a trap 129, 130 or 131 - then this is a trap
+ signaling a change on a physical port. Mark the flag physp_change_trap as TRUE. */
+ physp_change_trap = TRUE;
+ /* The source_lid should be based on the source_lid from the trap */
+ source_lid = p_ntci->data_details.ntc_129_131.lid;
+ }
+
+ /* If physp_change_trap is TRUE - the key will include the port number.
+ If not - the port_number in the key will be zero. */
+ if ( physp_change_trap == TRUE )
+ {
+ port_num = p_ntci->data_details.ntc_129_131.port_num;
+ __osm_trap_get_key(source_lid,
+ port_num,
+ p_ntci,
+ &trap_key);
+ }
+ else
+ __osm_trap_get_key(source_lid,
+ 0,
+ p_ntci,
+ &trap_key);
+
+ /* try to find it in the aging tracker */
+ num_received = cl_event_wheel_num_regs(&p_rcv->trap_aging_tracker,
+ trap_key);
+
+ /* Now we know how many times it provided this trap */
+ if (num_received > 10)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3804: "
+ "Received the trap %u times continuously.\n",
+ num_received);
+ /*
+ * If the trap provides info about a bad port
+ * we will mark it as unhealthy.
+ *
+ */
+ if (physp_change_trap == TRUE)
+ {
+ /* get the port */
+ p_physp = __get_physp_by_lid_and_num(
+ p_rcv,
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ port_num
+ );
+
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3805: "
+ "Fail to find physical port by lid:0x%02X num:%u\n",
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ p_ntci->data_details.ntc_129_131.port_num
+ );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Marking unhealthy physical port by lid:0x%02X num:%u\n",
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ p_ntci->data_details.ntc_129_131.port_num
+ );
+ /* check if the current state of the p_physp is healthy. If
+ it is - then this is a first change of state. Run a heavy sweep.
+ if it is not - no need to mark it again - just restart the timer. */
+ if ( osm_physp_is_healthy(p_physp) )
+ {
+ osm_physp_set_health(p_physp, FALSE);
+ /* Make sure we sweep again - force a heavy sweep. */
+ /* The sweep should be done only after the re-registration, or
+ else we'll be loosing track of the timer. */
+ run_heavy_sweep = TRUE;
+ }
+ /* If we are marking the port as unhealthy - we want to
+ keep this for a longer period of time then the
+ OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT. Use the
+ OSM_DEFAULT_UNHEALTHY_TIMEOUT */
+ event_wheel_timeout = OSM_DEFAULT_UNHEALTHY_TIMEOUT;
+ }
+ }
+ }
+
+ /* restart the aging anyway */
+ /* If physp_change_trap is TRUE - then use a callback to unset the
+ healthy bit. If not - no need to use a callback. */
+ if (physp_change_trap == TRUE )
+ cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+ trap_key,
+ cl_get_time_stamp() + event_wheel_timeout,
+ osm_trap_rcv_aging_tracker_callback, /* no callback */
+ p_rcv /* no conetxt */
+ );
+ else
+ cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+ trap_key,
+ cl_get_time_stamp() + event_wheel_timeout,
+ NULL, /* no callback */
+ NULL /* no conetxt */
+ );
+
+ /* If was already registered do nothing more */
+ if ( num_received > 10 && run_heavy_sweep == FALSE )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Continuously received this trap %u times. Ignoring it.\n",
+ num_received);
+ goto Exit;
+ }
+ }
+
+ /* do a sweep if we received a trap */
+ if (p_rcv->p_subn->opt.sweep_on_trap)
+ {
+ /* if this is trap number 128 or run_heavy_sweep is TRUE - update the
+ force_single_heavy_sweep flag of the subnet.
+ Sweep also on traps 144/145 - these traps signal a change on a certain
+ port capability/system image guid.
+ TODO: In the future we can change this to just getting PortInfo on
+ this port instead of sweeping the entire subnet. */
+ if (ib_notice_is_generic(p_ntci) &&
+ ( (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 128) ||
+ (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 144) ||
+ (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 145) ||
+ run_heavy_sweep ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Forcing immediate heavy sweep. "
+ "Received trap:%u \n",
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num) );
+
+ p_rcv->p_subn->force_immediate_heavy_sweep = TRUE;
+ }
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ OSM_SIGNAL_SWEEP );
+ }
+
+ /* If we reached here due to trap 129/130/131 - do not need to do
+ the notice report. Just goto exit. We know this is the case
+ if physp_change_trap is TRUE. */
+ if ( physp_change_trap == TRUE )
+ goto Exit;
+
+ /* Add a call to osm_report_notice */
+ /* We are going to report the notice - so need to fix the IssuerGID
+ accordingly. See IBA 1.1 P.653 or IBA 1.2 P.739 for details. */
+ if (is_gsi)
+ {
+ if (tmp_madw.mad_addr.addr_type.gsi.global_route)
+ {
+ cl_memcpy(&(p_ntci->issuer_gid),
+ &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid),
+ sizeof(ib_gid_t));
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3806: "
+ "Received gsi trap with global_route FALSE. "
+ "Cannot update issuer_gid!\n" );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* Need to use the IssuerLID. */
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) <= cl_ntoh16(source_lid) )
+ {
+ /* the source lid is out of range. */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "source lid is out of range:0x%X \n",
+ cl_ntoh16(source_lid) );
+
+ goto Exit;
+ }
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(source_lid) );
+ if ( p_port == 0)
+ {
+ /* We have the lid - but no corresponding port */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Cannot find port according to lid:0x%X \n",
+ cl_ntoh16(source_lid) );
+
+ goto Exit;
+ }
+
+ p_ntci->issuer_gid.unicast.prefix = p_rcv->p_subn->opt.subnet_prefix;
+ p_ntci->issuer_gid.unicast.interface_id = p_port->guid;
+ }
+
+ status = osm_report_notice(p_rcv->p_log, p_rcv->p_subn, p_ntci);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3803: "
+ "Error sending trap reports (%s).\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
+**********************************************************************/
+void
+__osm_trap_rcv_process_sm(
+ IN const osm_trap_rcv_t* const p_rcv,
+ IN const osm_remote_sm_t* const p_sm )
+{
+ /* const ib_sm_info_t* p_smi; */
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_sm );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_sm: "
+ "This function is not supported yet.\n");
+
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
+**********************************************************************/
+void
+__osm_trap_rcv_process_response(
+ IN const osm_trap_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_response );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_response: "
+ "This function is not supported yet.\n");
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_process(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ Determine if this is a request for our own Trap
+ or if this is a response to our request for another
+ SM's Trap.
+ */
+ if( ib_smp_is_response( p_smp ) )
+ {
+ __osm_trap_rcv_process_response( p_rcv, p_madw );
+ }
+ else
+ {
+ __osm_trap_rcv_process_request( p_rcv, p_madw );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_trap_rcv_ctrl_t.
+ * This object represents the Trap request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_trap_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_trap_rcv_process( ((osm_trap_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_construct(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_destroy(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl,
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_trap_rcv_ctrl_init );
+
+ osm_trap_rcv_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NOTICE,
+ __osm_trap_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_trap_rcv_ctrl_init: ERR 3901: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ucast_mgr_t.
+ * This file implements the LID Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * This flag is used for stopping the relaxation algorithm if no
+ * change detected during the fabric scan
+ */
+static boolean_t __some_hop_count_set;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_construct(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_destroy(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_destroy );
+
+ CL_ASSERT( p_mgr );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ucast_mgr_init(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN char* const p_report_buf,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_ucast_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_ucast_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+ p_mgr->p_report_buf = p_report_buf;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_dump_path_distribution(
+ IN const osm_ucast_mgr_t* const p_mgr,
+ IN const osm_switch_t* const p_sw )
+{
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ uint8_t i;
+ uint8_t num_ports;
+ uint32_t num_paths;
+ ib_net64_t remote_guid_ho;
+ char line[OSM_REPORT_LINE_SIZE];
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_dump_path_distribution );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+ sprintf( p_mgr->p_report_buf, "osm_ucast_mgr_dump_path_distribution: "
+ "Switch 0x%" PRIx64 "\n"
+ "Port : Path Count Through Port",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+
+ for( i = 0; i < num_ports; i++ )
+ {
+ num_paths = osm_switch_path_count_get( p_sw , i );
+ sprintf( line, "\n %03u : %u", i, num_paths );
+ strcat( p_mgr->p_report_buf, line );
+ if( i == 0 )
+ {
+ strcat( p_mgr->p_report_buf, " (switch management port)" );
+ continue;
+ }
+
+ p_remote_node = osm_node_get_remote_node(
+ p_node, i, NULL );
+
+ if( p_remote_node == NULL )
+ continue;
+
+ remote_guid_ho = cl_ntoh64(
+ osm_node_get_node_guid( p_remote_node ) );
+
+ switch( osm_node_get_remote_type( p_node, i ) )
+ {
+ case IB_NODE_TYPE_SWITCH:
+ strcat( p_mgr->p_report_buf, " (link to switch" );
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ strcat( p_mgr->p_report_buf, " (link to router" );
+ break;
+ case IB_NODE_TYPE_CA:
+ strcat( p_mgr->p_report_buf, " (link to CA" );
+ break;
+ default:
+ strcat( p_mgr->p_report_buf, " (link to unknown type, node" );
+ break;
+ }
+
+ sprintf( line, " 0x%" PRIx64 ")", remote_guid_ho );
+ strcat( p_mgr->p_report_buf, line );
+ }
+
+ strcat( p_mgr->p_report_buf, "\n" );
+
+ osm_log_raw( p_mgr->p_log, OSM_LOG_ROUTING, p_mgr->p_report_buf );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_dump_ucast_routes(
+ IN const osm_ucast_mgr_t* const p_mgr,
+ IN const osm_switch_t* const p_sw )
+{
+ const osm_node_t* p_node;
+ uint8_t port_num;
+ uint8_t num_hops;
+ uint8_t best_hops;
+ uint8_t best_port;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ char line[OSM_REPORT_LINE_SIZE];
+ uint32_t line_num = 0;
+ FILE * p_fdbFile;
+ boolean_t ui_ucast_fdb_assign_func_defined;
+ char *file_name = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_dump_ucast_routes );
+
+ if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ goto Exit;
+
+ file_name =
+ (char*)cl_malloc(strlen(p_mgr->p_subn->opt.dump_files_dir) + 10);
+
+ CL_ASSERT(file_name);
+
+ strcpy(file_name, p_mgr->p_subn->opt.dump_files_dir);
+ strcat(file_name,"/osm.fdbs");
+
+ /* Open the file or error */
+ p_fdbFile = fopen(file_name, "a");
+ if (! p_fdbFile)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_ucast_mgr_dump_ucast_routes: ERR 3A12: "
+ "Fail to open fdb file (%s).\n",
+ file_name );
+ goto Exit;
+ }
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+
+ for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ if( line_num == 0 )
+ {
+ sprintf( p_mgr->p_report_buf, "osm_ucast_mgr_dump_ucast_routes: "
+ "Switch 0x%016" PRIx64 "\n"
+ "LID : Port : Hops : Optimal\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ line_num++;
+ }
+
+ port_num = osm_switch_get_port_by_lid( p_sw, lid_ho );
+ if( port_num == OSM_NO_PATH )
+ {
+ /*
+ This may occur if there are 'holes' in the existing
+ LID assignemnts. Running SM with --reassign_lids
+ will reassign and compress the LID range. The
+ subnet should work fine either way.
+ */
+ sprintf( line, "0x%04X : UNREACHABLE\n", lid_ho );
+ strcat( p_mgr->p_report_buf, line );
+ line_num++;
+ continue;
+ }
+ /*
+ Switches can lie about which port routes a given
+ lid due to a recent reconfiguration of the subnet.
+ Therefore, ensure that the hop count is better than
+ OSM_NO_PATH.
+ */
+ num_hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+ if( num_hops == OSM_NO_PATH )
+ {
+ sprintf( line, "0x%04X : UNREACHABLE\n", lid_ho );
+ strcat( p_mgr->p_report_buf, line );
+ line_num++;
+ continue;
+ }
+
+ best_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+ sprintf( line, "0x%04X : %03u : %02u : ",
+ lid_ho, port_num, num_hops );
+ strcat( p_mgr->p_report_buf, line );
+
+ if( best_hops == num_hops )
+ strcat( p_mgr->p_report_buf, "yes" );
+ else
+ {
+ if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign) {
+ ui_ucast_fdb_assign_func_defined = TRUE;
+ } else {
+ ui_ucast_fdb_assign_func_defined = FALSE;
+ }
+ best_port = osm_switch_recommend_path(
+ p_sw, lid_ho, TRUE,
+ NULL, NULL, NULL, NULL, /* No LMC Optimization */
+ 0xffffffff, ui_ucast_fdb_assign_func_defined );
+ sprintf( line, "No %u hop path possible via port %u!",
+ best_hops, best_port );
+ strcat( p_mgr->p_report_buf, line );
+ }
+
+ strcat( p_mgr->p_report_buf, "\n" );
+
+ if( ++line_num >= OSM_REPORT_BUF_THRESHOLD )
+ {
+ fprintf(p_fdbFile,"%s",p_mgr->p_report_buf );
+ line_num = 0;
+ }
+ }
+
+ if( line_num != 0 )
+ fprintf(p_fdbFile,"%s\n",p_mgr->p_report_buf );
+
+ fclose(p_fdbFile);
+
+ Exit:
+ if (file_name)
+ cl_free(file_name);
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Add each switch's own LID to its LID matrix.
+**********************************************************************/
+static void
+__osm_ucast_mgr_process_hop_0(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ uint16_t lid_ho;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_hop_0 );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ /*
+ Starting a rebuild, so notify the switch so it can
+ clear tables, etc...
+ */
+ osm_switch_prepare_path_rebuild( p_sw );
+
+ lid_ho = cl_ntoh16( osm_node_get_base_lid( p_node, 0 ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_hop_0: "
+ "Processing switch GUID 0x%" PRIx64 ", LID 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ lid_ho );
+ }
+
+ status = osm_switch_set_hops( p_sw, lid_ho, 0, 0 );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_hop_0: ERR 3A02: "
+ "Setting hop count failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbor(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN osm_switch_t* const p_remote_sw,
+ IN const uint8_t port_num,
+ IN const uint8_t remote_port_num )
+{
+ uint16_t lid_ho;
+ uint16_t max_lid_ho;
+ osm_node_t* p_node;
+ const osm_node_t* p_remote_node;
+ uint8_t hops;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbor );
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_remote_sw );
+ CL_ASSERT( port_num );
+ CL_ASSERT( remote_port_num );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_remote_node = osm_switch_get_node_ptr( p_remote_sw );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_remote_node );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+ CL_ASSERT( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbor: "
+ "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 "\n"
+ "\t\t\t\tport 0x%X, remote port 0x%X.\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ port_num, remote_port_num );
+ }
+
+ /*
+ Iterate through all the LIDs in the neighbor switch.
+ */
+ max_lid_ho = osm_switch_get_max_lid_ho( p_remote_sw );
+
+ /*
+ Make sure the local lid matrix has enough room to hold
+ all the LID info coming from the remote LID matrix.
+ */
+ osm_switch_set_min_lid_size( p_sw, max_lid_ho );
+
+ hops = OSM_NO_PATH;
+ for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ /*
+ Find the lowest hop count value to this LID.
+ */
+ hops = osm_switch_get_least_hops( p_remote_sw, lid_ho );
+
+ if( hops != OSM_NO_PATH )
+ {
+ /*
+ Increment hop count of the neighbor by 1, since it
+ takes 1 hop to get to the neighbor.
+ */
+ hops++;
+
+ CL_ASSERT( hops <= osm_switch_get_hop_count( p_sw, lid_ho,
+ port_num ) );
+ if( osm_switch_get_hop_count( p_sw, lid_ho,
+ port_num ) > hops )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbor: "
+ "New best path is %u hops for LID 0x%X.\n",
+ hops, lid_ho );
+ }
+
+ /* mark the fact we have got to change anything */
+ __some_hop_count_set = TRUE;
+
+ status = osm_switch_set_hops( p_sw, lid_ho,
+ port_num, hops );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_neighbor: ERR 3A03: "
+ "Setting hop count failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaf(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ uint16_t i;
+ uint16_t base_lid_ho;
+ uint16_t max_lid_ho;
+ uint8_t lmc;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaf );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_remote_node );
+ CL_ASSERT( port_num );
+ CL_ASSERT( remote_port_num );
+
+ switch( osm_node_get_type( p_remote_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ case IB_NODE_TYPE_ROUTER:
+ base_lid_ho = cl_ntoh16( osm_node_get_base_lid(
+ p_remote_node, remote_port_num ) );
+ lmc = osm_node_get_lmc( p_remote_node, remote_port_num );
+ break;
+/* case IB_NODE_TYPE_SWITCH: */
+/* base_lid_ho = cl_ntoh16( osm_node_get_base_lid( */
+/* p_remote_node, 0 ) ); */
+/* lmc = 0; */
+/* break; */
+
+ default:
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_leaf: ERR 3A01: "
+ "Bad node type %u, GUID = 0x%" PRIx64 ".\n",
+ osm_node_get_type( p_remote_node ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ goto Exit;
+ }
+
+ max_lid_ho = (uint16_t)(base_lid_ho + (1 << lmc) - 1 );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_leaf: "
+ "Discovered LIDs [0x%X,0x%X]\n"
+ "\t\t\t\tport number 0x%X, node 0x%" PRIx64 ".\n",
+ base_lid_ho, max_lid_ho,
+ port_num, cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ for( i = base_lid_ho; i <= max_lid_ho; i++ )
+ osm_switch_set_hops( p_sw, i, port_num, 1 );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaves(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ uint32_t port_num;
+ uint8_t remote_port_num;
+ uint32_t num_ports;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaves );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_leaves: "
+ "Processing switch 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ /*
+ Add the LIDs of all leaves of this switch to the LID matrix.
+ Don't bother processing loopback paths from one port of
+ this switch to the another port.
+ Don't process neighbor switches yet.
+ Start with port 1 to skip the switch's management port.
+ */
+ num_ports = osm_node_get_num_physp( p_node );
+
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_remote_node = osm_node_get_remote_node( p_node,
+ (uint8_t)port_num, &remote_port_num );
+
+ if( p_remote_node && (p_remote_node != p_node )
+ && (osm_node_get_type( p_remote_node )
+ != IB_NODE_TYPE_SWITCH ))
+ {
+ __osm_ucast_mgr_process_leaf(
+ p_mgr,
+ p_sw,
+ p_node,
+ (uint8_t)port_num,
+ p_remote_node,
+ remote_port_num );
+ }
+ }
+
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_port(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN const osm_port_t* const p_port )
+{
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint8_t port;
+ boolean_t ignore_existing, is_ignored_by_port_pro;
+ ib_net64_t node_guid;
+ boolean_t ui_ucast_fdb_assign_func_defined;
+ /*
+ The following are temporary structures that will aid
+ in providing better routing in LMC > 0 situations
+ */
+ uint16_t lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
+ uint64_t* remote_sys_guids = NULL;
+ uint64_t* remote_node_guids = NULL;
+ uint16_t num_used_sys = 0;
+ uint16_t num_used_nodes = 0;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_port );
+
+ remote_sys_guids = cl_zalloc( sizeof(uint64_t) * lids_per_port );
+ if( remote_sys_guids == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A09: "
+ "Cannot allocate array. Memory insufficient.\n");
+ goto Exit;
+ }
+
+ remote_node_guids = cl_zalloc( sizeof(uint64_t) * lids_per_port );
+ if( remote_node_guids == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A0A: "
+ "Cannot allocate array. Memory insufficient.\n");
+ goto Exit;
+ }
+
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+ /* If the lids are zero - then there was some problem with the initialization.
+ Don't handle this port. */
+ if (min_lid_ho == 0 || max_lid_ho == 0)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A04: "
+ "Port 0x%" PRIx64 " has LID 0. An initialization "
+ "error occurred. Ignoring port\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "Processing port 0x%" PRIx64
+ ", LIDs [0x%X,0x%X].\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ min_lid_ho, max_lid_ho );
+ }
+
+ /*
+ TO DO -
+ This should be runtime error, not an CL_ASSERT()
+ */
+ CL_ASSERT( max_lid_ho < osm_switch_get_fwd_tbl_size( p_sw ) );
+
+ node_guid = osm_node_get_node_guid(osm_switch_get_node_ptr( p_sw ) );
+
+ /* Flag to mark whether or not a ui ucast fdb assign function was given */
+ if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
+ ui_ucast_fdb_assign_func_defined = TRUE;
+ else
+ ui_ucast_fdb_assign_func_defined = FALSE;
+
+ /*
+ If the user request a complete subnet reconfiguration,
+ then ignore existing paths when choosing paths now.
+ Note that if there is a ui ucast fdb assign function - then the
+ ignore_existing should be false.
+ */
+ ignore_existing = p_mgr->p_subn->ignore_existing_lfts &&
+ (!ui_ucast_fdb_assign_func_defined) ;
+
+ /*
+ The lid matrix contains the number of hops to each
+ lid from each port. From this information we determine
+ how best to distribute the LID range across the ports
+ that can reach those LIDs.
+ */
+ for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ /* Use the enhanced algorithm only for LMC > 0 */
+ if (lids_per_port > 1)
+ port = osm_switch_recommend_path( p_sw, lid_ho, ignore_existing,
+ remote_sys_guids, &num_used_sys,
+ remote_node_guids, &num_used_nodes,
+ p_mgr->p_subn->opt.max_port_profile,
+ ui_ucast_fdb_assign_func_defined );
+ else
+ port = osm_switch_recommend_path( p_sw, lid_ho, ignore_existing,
+ NULL, NULL, NULL, NULL,
+ p_mgr->p_subn->opt.max_port_profile,
+ ui_ucast_fdb_assign_func_defined );
+
+ /*
+ There might be no path to the target:
+ */
+ if (port == OSM_NO_PATH)
+ {
+ /* do not try to overwrite the ppro of non existing port ... */
+ is_ignored_by_port_pro = TRUE;
+
+ /* Up/Down routing can cause unreachable routes between some
+ switches so we do not report that as an error in that case */
+ if (!p_mgr->p_subn->opt.updn_activate)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A08: "
+ "No path to get to LID 0x%X from switch 0x%" PRIx64 ".\n",
+ lid_ho, cl_ntoh64( node_guid ) );
+ /* trigger a new sweep - try again ... */
+ p_mgr->p_subn->subnet_initialization_error = TRUE;
+ }
+ else
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "No path to get to LID 0x%X from switch 0x%" PRIx64 ".\n",
+ lid_ho, cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "Routing LID 0x%X to port 0x%X"
+ "\n\t\t\t\tFor switch 0x%" PRIx64 ".\n",
+ lid_ho, port, cl_ntoh64( node_guid ) );
+
+ /*
+ we would like to optionally ignore this port in equalization
+ like in the case of the Mellanox Anafa Internal PCI TCA port
+ */
+ is_ignored_by_port_pro =
+ osm_port_pro_is_ignored_port(p_mgr->p_subn, cl_ntoh64(node_guid), port);
+
+ /*
+ We also would ignore this route if the target lid if of a switch
+ and the port_profile_switch_node is not TRUE
+ */
+ if (! p_mgr->p_subn->opt.port_profile_switch_nodes)
+ {
+ is_ignored_by_port_pro |=
+ (osm_node_get_type(osm_port_get_parent_node(p_port)) ==
+ IB_NODE_TYPE_SWITCH);
+ }
+ }
+
+ /*
+ We have selected the port for this LID.
+ Write it to the forwarding tables.
+ */
+ osm_switch_set_path( p_sw, lid_ho, port, is_ignored_by_port_pro);
+ }
+ Exit:
+ if (remote_sys_guids) cl_free(remote_sys_guids);
+ if (remote_node_guids) cl_free(remote_node_guids);
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_set_table(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw )
+{
+ osm_node_t *p_node;
+ osm_dr_path_t *p_path;
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ ib_switch_info_t si;
+ uint32_t block_id_ho = 0;
+ uint8_t block[IB_SMP_DATA_SIZE];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_set_table );
+
+ CL_ASSERT( p_mgr );
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( p_node );
+
+ p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ CL_ASSERT( p_path );
+
+ /*
+ Set the top of the unicast forwarding table.
+ */
+ si = *osm_switch_get_si_ptr( p_sw );
+ si.lin_top = cl_hton16( osm_switch_get_max_lid_ho( p_sw ) );
+
+ /* check to see if the change state bit is on. If it is - then we
+ need to clear it. */
+ if( ib_switch_info_get_state_change( &si ) )
+ si.life_state = ( (p_mgr->p_subn->opt.packet_life_time <<3 )
+ | ( si.life_state & IB_SWITCH_PSC ) ) & 0xfc;
+ else
+ si.life_state = (p_mgr->p_subn->opt.packet_life_time <<3 ) & 0xf8;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_set_table: "
+ "Setting switch FT top to LID 0x%X.\n",
+ osm_switch_get_max_lid_ho( p_sw ) );
+ }
+
+ context.si_context.light_sweep = FALSE;
+ context.si_context.node_guid = osm_node_get_node_guid( p_node );
+ context.si_context.set_method = TRUE;
+
+ status = osm_req_set( p_mgr->p_req,
+ p_path,
+ (uint8_t*)&si,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_set_table: ERR 3A06: "
+ "Sending SwitchInfo attribute failed (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ /*
+ Send linear forwarding table blocks to the switch
+ as long as the switch indicates it has blocks needing
+ configuration.
+ */
+
+ context.lft_context.node_guid = osm_node_get_node_guid( p_node );
+ context.lft_context.set_method = TRUE;
+
+ while( osm_switch_get_fwd_tbl_block( p_sw, block_id_ho, block ) )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_set_table: "
+ "Writing FT block %u.\n", block_id_ho );
+ }
+
+ status = osm_req_set( p_mgr->p_req,
+ p_path,
+ block,
+ IB_MAD_ATTR_LIN_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_set_table: ERR 3A05: "
+ "Sending linear fwd. tbl. block failed (%s).\n",
+ ib_get_err_str( status ) );
+ }
+
+ block_id_ho++;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_tbl(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ const osm_port_t *p_port;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_tbl );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_tbl: "
+ "Processing switch 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ Iterate through every port setting LID routes for each
+ port based on base LID and LMC value.
+ */
+
+ for( p_port = (osm_port_t*)cl_qmap_head( p_port_tbl );
+ p_port != (osm_port_t*)cl_qmap_end( p_port_tbl );
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+ {
+ __osm_ucast_mgr_process_port( p_mgr, p_sw, p_port );
+ }
+
+ __osm_ucast_mgr_set_table( p_mgr, p_sw );
+
+ osm_ucast_mgr_dump_path_distribution( p_mgr, p_sw );
+ osm_ucast_mgr_dump_ucast_routes( p_mgr, p_sw );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbors(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ ib_net64_t remote_node_guid;
+ osm_switch_t *p_remote_sw;
+ uint32_t port_num;
+ uint8_t remote_port_num;
+ uint32_t num_ports;
+ osm_physp_t* p_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbors );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbors: "
+ "Processing switch with GUID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ num_ports = osm_node_get_num_physp( p_node );
+
+ /*
+ Start with port 1 to skip the switch's management port.
+ */
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_remote_node = osm_node_get_remote_node( p_node,
+ (uint8_t)port_num, &remote_port_num );
+
+ if( p_remote_node && (p_remote_node != p_node )
+ && (osm_node_get_type( p_remote_node )
+ == IB_NODE_TYPE_SWITCH ))
+ {
+ /* make sure the link is healthy. If it is not - don't
+ propagate through it. */
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ if (!osm_link_is_healthy( p_physp ) ) continue;
+
+ remote_node_guid = osm_node_get_node_guid( p_remote_node );
+
+ p_remote_sw = (osm_switch_t*)cl_qmap_get(
+ &p_mgr->p_subn->sw_guid_tbl, remote_node_guid );
+
+ if( p_remote_sw == (osm_switch_t*)cl_qmap_end(
+ &p_mgr->p_subn->sw_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_neighbors: ERR 3A07: "
+ "No switch object for Node GUID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( remote_node_guid ) );
+ }
+ else
+ {
+ __osm_ucast_mgr_process_neighbor(
+ p_mgr,
+ p_sw,
+ p_remote_sw,
+ (uint8_t)port_num,
+ remote_port_num );
+ }
+ }
+ }
+
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_ucast_mgr_process(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ uint32_t i;
+ uint32_t iteration_max;
+ osm_signal_t signal;
+ cl_qmap_t *p_sw_guid_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process );
+
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ osm_log(p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_ucast_mgr_process: "
+ "Starting switches Min Hop Table Assignment.\n");
+
+ /*
+ Set the switch matrixes for each switch's own port 0 LID,
+ then set the lid matrixes for the each switch's leaf nodes.
+ */
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_hop_0, p_mgr );
+
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_leaves, p_mgr );
+
+ /*
+ Get the switch matrixes for each switch's neighbors.
+ This process requires a number of iterations equal to
+ the number of switches in the subnet minus 1.
+
+ In each iteration, a switch learns the lid/port/hop
+ information (as contained by a switch's lid matrix) from its
+ immediate neighbors. After each
+ iteration, a switch (and it's neighbors) know more
+ routing information than it did on the previous iteration.
+ Thus, by repeatedly absorbing the routing information of
+ neighbor switches, every switch eventually learns how to
+ route all LIDs on the subnet.
+
+ Note that there may not be any switches in the subnet if
+ we are in simple p2p configuration.
+ */
+ iteration_max = cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl );
+
+ /*
+ If there are switches in the subnet, iterate until the lid
+ matrix has been constructed. Otherwise, just immediately
+ indicate we're done if no switches exist.
+ */
+ if( iteration_max )
+ {
+ iteration_max--;
+
+ /*
+ we need to find out when the propagation of
+ hop counts has relaxed. So this global variable
+ is preset to 0 on each iteration and if
+ if non of the switches was set will exit the
+ while loop
+ */
+ __some_hop_count_set = TRUE;
+ for( i = 0; (i < iteration_max) && __some_hop_count_set; i++ )
+ {
+ __some_hop_count_set = FALSE;
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_neighbors, p_mgr );
+ }
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_process: "
+ "Min-hop propagated in %d steps\n",
+ i
+ );
+
+ /*
+ This is the place where we can load pre-defined routes
+ into the switches fwd_tbl structures.
+
+ Later code will use these values if not configured for
+ re-assignment.
+ */
+ if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_process: "
+ "Invoking UI function pfn_ui_ucast_fdb_assign\n");
+ }
+ p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign(p_mgr->p_subn->opt.ui_ucast_fdb_assign_ctx);
+ } else {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_process: "
+ "UI pfn was not invoked\n");
+ }
+
+ osm_log(p_mgr->p_log, OSM_LOG_INFO,
+ "osm_ucast_mgr_process: "
+ "Min Hop Tables configured on all switches.\n");
+
+ /*
+ Now that the lid matrixes have been built, we can
+ build and download the switch forwarding tables.
+ */
+
+ /* initialize the fdb dump file: */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ unlink("/tmp/osm.fdbs");
+
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_tbl, p_mgr );
+
+ /*
+ For now dont' bother checking if the switch forwarding tables
+ actually needed updating. The current code will always update
+ them, and thus leave transactions pending on the wire.
+ Therefore, return OSM_SIGNAL_DONE_PENDING.
+ */
+
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+ else
+ signal = OSM_SIGNAL_DONE;
+
+ osm_log(p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_ucast_mgr_process: "
+ "LFT Tables configured on all switches.\n");
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of Up Down Algorithm using ranking & Min Hop
+ * Calculation functions
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_ucast_updn.h>
+#include <stdlib.h>
+
+
+/* ///////////////////////////////// */
+/* Globals */
+/* ///////////////////////////////// */
+/* This var is pre defined and initialized */
+extern osm_opensm_t osm;
+
+/**********************************************************************
+ **********************************************************************/
+/* This function returns direction based on rank and guid info of current &
+ remote ports */
+
+updn_switch_dir_t
+__updn_get_dir(IN uint8_t cur_rank,
+ IN uint8_t rem_rank,
+ IN uint64_t cur_guid,
+ IN uint64_t rem_guid)
+{
+ uint32_t i = 0, max_num_guids = osm.p_updn_ucast_routing->updn_ucast_reg_inputs.num_guids;
+ uint64_t *p_guid = osm.p_updn_ucast_routing->updn_ucast_reg_inputs.guid_list;
+ boolean_t cur_is_root = FALSE , rem_is_root = FALSE;
+
+ /* HACK : comes to solve root nodes connection, in a classic subnet root nodes does not connect
+ directly , but in case they are we assign to root node an UP direction to allow UPDN discover
+ correctly (and not from the point of view of the last root node) the subnet .
+ */
+
+ for ( i = 0 ; i < max_num_guids ; i++ )
+ {
+ if (cur_guid == p_guid[i])
+ cur_is_root = TRUE;
+ if (rem_guid == p_guid[i])
+ rem_is_root = TRUE;
+ }
+ if (cur_is_root && rem_is_root)
+ return UP;
+
+
+ if (cur_rank < rem_rank)
+ return DOWN;
+ else if (cur_rank > rem_rank)
+ return UP;
+ else
+ {
+ /* Equal rank , decide by guid number , bigger == UP direction */
+ if (cur_guid > rem_guid)
+ return UP;
+ else
+ return DOWN;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* This function creates a new element of updn_next_step_t type then return its
+ pointer , Null if malloc has failed */
+updn_next_step_t*
+__updn_create_updn_next_step_t(IN updn_switch_dir_t state, IN osm_switch_t* const p_sw)
+{
+ updn_next_step_t *p_next_step;
+
+ p_next_step = (updn_next_step_t*) cl_zalloc(sizeof(*p_next_step));
+ CL_ASSERT (p_next_step != NULL);
+
+ p_next_step->state = state;
+ p_next_step->p_sw = p_sw;
+ return p_next_step;
+
+}
+/**********************************************************************
+ **********************************************************************/
+/* This function updates an element in the qmap list by guid index and rank value */
+/* Return 0 if no need to futher update 1 if brought a new value */
+
+int
+__updn_update_rank(
+ IN cl_qmap_t *p_guid_rank_tbl,
+ IN ib_net64_t guid_index,
+ IN uint8_t rank)
+{
+ updn_rank_t *p_updn_rank;
+
+ p_updn_rank = (updn_rank_t*) cl_qmap_get(p_guid_rank_tbl, guid_index);
+ if (p_updn_rank == (updn_rank_t*) cl_qmap_end(p_guid_rank_tbl))
+ {
+ p_updn_rank = (updn_rank_t*) cl_malloc(sizeof(updn_rank_t));
+ CL_ASSERT (p_updn_rank);
+
+ p_updn_rank->rank = rank;
+
+ cl_qmap_insert(p_guid_rank_tbl, guid_index , &p_updn_rank->map_item);
+ return 1;
+ }
+ else
+ {
+ if (p_updn_rank->rank > rank)
+ {
+ p_updn_rank->rank = rank;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**********************************************************************
+ * This function do the bfs of min hop table calculation by guid index as a
+ * starting point.
+ **********************************************************************/
+int
+__updn_bfs_by_node(IN osm_subn_t *p_subn, IN ib_net64_t guid_index, IN cl_qmap_t *p_guid_rank_tbl)
+{
+ /* Init local vars */
+ osm_port_t *p_port;
+ osm_switch_t *p_self_node = NULL;
+ uint8_t pn,pn_rem;
+ osm_physp_t *p_physp, *p_remote_physp;
+ cl_list_t *p_currList,*p_nextList;
+ uint16_t root_lid, max_sw_lid;
+ updn_next_step_t *p_updn_switch,*p_tmp;
+ updn_switch_dir_t next_dir,current_dir;
+
+ OSM_LOG_ENTER( &(osm.log) , __updn_bfs_by_node);
+
+ /* Init the list pointers */
+ p_nextList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_currList = p_nextList;
+
+ p_port = (osm_port_t*) cl_qmap_get(&(p_subn->port_guid_tbl),guid_index);
+ /* TODO : check if p_port is not NULL */
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* Check valid pointer */
+ if (!p_physp || !osm_physp_is_valid(p_physp ))
+ {
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+ /* The Root BFS - lid */
+ root_lid = cl_ntoh16(osm_physp_get_base_lid( p_physp ));
+ /* printf ("-V- BFS through lid : 0x%x\n",root_lid); */
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting lid : 0x%x \n", root_lid);
+
+ if (osm_node_get_type( p_port->p_node ) == IB_NODE_TYPE_SWITCH)
+ {
+ p_self_node = osm_get_switch_by_guid(p_subn, guid_index);
+ /* Update its Min Hop Table */
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Update Min Hop Table of guid 0x%" PRIx64 "\n"
+ , cl_ntoh64(p_port->guid));
+ osm_switch_set_hops(p_self_node, root_lid , 0, 0);
+ }
+ else
+ {
+ /* This is an HCA need to take its remote port */
+ p_remote_physp = p_physp->p_remote_physp;
+ /*
+ make sure that the following occur:
+ 1. The port isn't NULL
+ 2. The port is a valid port
+ */
+ if ( p_remote_physp && osm_physp_is_valid ( p_remote_physp ))
+ {
+ /* Check if the remote port is a switch, if it is update root_lid,
+ Min Hop Table */
+ if (osm_node_get_type(p_remote_physp->p_node) != IB_NODE_TYPE_SWITCH)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA07: "
+ "This is a non switched subnet OR non valid connection, cannot perform Algorithm\n");
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ } else
+ {
+ p_self_node = osm_get_switch_by_guid(p_subn,
+ osm_physp_get_port_guid
+ (p_remote_physp));
+ max_sw_lid = osm_switch_get_max_lid_ho(p_self_node);
+ if ((1 <= root_lid) && (root_lid <= max_sw_lid))
+ /* Update its Min Hop Table */
+ {
+ /* NOTE : Check if there is a function which prints the Min Hop Table */
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Update Min Hop Table of guid 0x%" PRIx64 "\n"
+ , cl_ntoh64(p_remote_physp->port_guid));
+ osm_switch_set_hops(p_self_node, root_lid
+ , p_remote_physp->port_num, 1);
+
+ } else
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA09: "
+ " Invalid lid value 0x%x for switch 0x%" PRIx64 "\n", root_lid
+ , cl_ntoh64(p_self_node->p_node->node_info.port_guid));
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+ }
+ }
+ }
+
+ CL_ASSERT(p_self_node);
+
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting from switch- port guid 0x%" PRIx64 ".\n"
+ , cl_ntoh64(p_self_node->p_node->node_info.port_guid));
+
+ /* Update list with the updn_next_step_t new element */
+ /* NOTE : When inserting an item which is a pointer to a struct , does remove
+ action also free its memory */
+ if (!(p_tmp=__updn_create_updn_next_step_t(UP, p_self_node)))
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA08: "
+ "Could not create updn_next_step_t\n");
+ return 1;
+ }
+
+ cl_list_insert_tail(p_currList,p_tmp );
+
+ /* BFS the list till no next element */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "__updn_bfs_by_node:"
+ "BFS the subnet [\n");
+
+ while (!cl_is_list_empty(p_currList))
+ {
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting a new iteration with %d elements in current list\n", cl_list_count(p_currList));
+ /* Init the switch directed list */
+ p_nextList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ /* Go over all current list items till it's empty */
+ /* printf ("-V- In inner while\n"); */
+ p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+ /* While there is a pointer to updn struct we continue to BFS */
+ while (p_updn_switch)
+ {
+ current_dir = p_updn_switch->state;
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Visiting port guid 0x%" PRIx64 "\n"
+ , cl_ntoh64(p_updn_switch->p_sw->p_node->node_info.port_guid));
+ /* Go over all ports of the switch and find unvisited remote nodes */
+ for ( pn = 0; pn < osm_switch_get_num_ports(p_updn_switch->p_sw); pn++ )
+ {
+ /* printf("-V- Inner for in port num %d\n", pn); */
+ osm_node_t *p_remote_node;
+ cl_list_iterator_t updn_switch_iterator;
+ boolean_t HasVisited=FALSE;
+ ib_net64_t remote_guid,current_guid;
+ updn_rank_t *p_rem_rank,*p_cur_rank;
+ uint8_t current_min_hop,remote_min_hop,set_hop_return_value;
+ osm_switch_t *p_remote_sw;
+
+ current_guid = osm_node_get_node_guid(p_updn_switch->p_sw->p_node);
+ p_remote_node = osm_node_get_remote_node( p_updn_switch->p_sw->p_node
+ , pn, &pn_rem );
+ /* If no remote node OR remote node is not a SWITCH
+ continue to next pn */
+ if( !p_remote_node ||
+ (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) )
+ continue;
+ /* Fetch remote guid only after validation of remote node */
+ remote_guid = osm_node_get_node_guid(p_remote_node);
+ /* printf ("-V- Current guid : 0x%" PRIx64 " Remote guid : 0x%" PRIx64 "\n" */
+ /* , cl_ntoh64(current_guid), cl_ntoh64(remote_guid)); */
+ p_remote_sw = osm_get_switch_by_guid(p_subn, remote_guid);
+ p_rem_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, remote_guid);
+ p_cur_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, current_guid);
+ /* Decide which direction to mark it (UP/DOWN) */
+ next_dir = __updn_get_dir (p_cur_rank->rank, p_rem_rank->rank,
+ current_guid, remote_guid);
+
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "move from 0x%016" PRIx64 " rank:%u "
+ "to 0x%016" PRIx64" rank:%u\n",
+ cl_ntoh64(current_guid), p_cur_rank->rank,
+ cl_ntoh64(remote_guid), p_rem_rank->rank);
+ /* Check if this is a legal step : the only illegal step is going
+ from DOWN to UP */
+ if ((current_dir == DOWN) && (next_dir == UP))
+ {
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64"\n",
+ cl_ntoh64(current_guid), cl_ntoh64(remote_guid));
+ /* Illegal step */
+ continue;
+ }
+ /* Set MinHop value for the current lid */
+ current_min_hop = osm_switch_get_least_hops(p_updn_switch->p_sw,root_lid);
+ /* Check hop count if better insert into NextState list && update
+ the remote node Min Hop Table */
+ remote_min_hop = osm_switch_get_hop_count(p_remote_sw,root_lid, pn_rem);
+ if (current_min_hop + 1 < remote_min_hop)
+ {
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node (less):"
+ "Setting Min Hop Table of switch : 0x%" PRIx64
+ "\n\t\tCurrent hop count is : %d , next hop count : %d"
+ "\n\tlid to set : 0x%x"
+ "\n\tport number : %d"
+ " \n\thops number: %d\n"
+ , cl_ntoh64(remote_guid), remote_min_hop,current_min_hop+1, root_lid, pn_rem,current_min_hop+1);
+ set_hop_return_value=osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop+1);
+ if (set_hop_return_value)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node (less) ERR AA1: "
+ "Invalid value returned from set min hop is : %d\n", set_hop_return_value);
+ }
+ /* Check if remote port is allready has been visited */
+ updn_switch_iterator = cl_list_head(p_nextList);
+ while( updn_switch_iterator != cl_list_end(p_nextList) )
+ {
+ updn_next_step_t *p_updn;
+ p_updn = (updn_next_step_t*)cl_list_obj(updn_switch_iterator);
+ /* Mark HasVisited only if:
+ 1. Same node guid
+ 2. Same direction
+ */
+ if ((p_updn->p_sw->p_node == p_remote_node) && (p_updn->state == next_dir))
+ HasVisited = TRUE;
+ updn_switch_iterator = cl_list_next(updn_switch_iterator);
+ }
+ if (!HasVisited)
+ {
+ /* Insert updn_switch item into the next list */
+ if(!(p_tmp=__updn_create_updn_next_step_t(next_dir, p_remote_sw)))
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA2: "
+ "Could not create updn_next_step_t\n");
+ return 1;
+ }
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node: "
+ "Inserting a new element to the next list : guid=0x%" PRIx64 " %s\n"
+ , cl_ntoh64(p_tmp->p_sw->p_node->node_info.port_guid),
+ (p_tmp->state == UP ? "UP" : "DOWN")
+ );
+ cl_list_insert_tail(p_nextList, p_tmp);
+ }
+ /* If the same value only update entry - at the min hop table */
+ } else if (current_min_hop + 1 == osm_switch_get_hop_count(p_remote_sw
+ , root_lid
+ , pn_rem))
+ {
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "__updn_bfs_by_node (equal):"
+ "Setting Min Hop Table of switch : 0x%" PRIx64
+ "\n\t\tCurrent hop count is : %d , next hop count : %d"
+ "\n\tlid to set : 0x%x"
+ "\n\tport number : %d"
+ "\n\thops number: %d\n"
+ , cl_ntoh64(remote_guid), osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem)
+ , current_min_hop+1, root_lid, pn_rem, current_min_hop+1);
+ set_hop_return_value=osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop+1);
+
+ if (set_hop_return_value)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "__updn_bfs_by_node (less) ERR AA3: "
+ "Invalid value returned from set min hop is : %d\n", set_hop_return_value);
+ }
+ }
+ }
+ cl_free (p_updn_switch);
+ p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+ }
+ /* Cleanup p_currList */
+ cl_list_destroy( p_currList );
+ cl_free (p_currList);
+
+ /* Reassign p_currList to p_nextList */
+ p_currList = p_nextList;
+ }
+ /* Cleanup p_currList - Had the pointer to cl_list_t */
+ cl_list_destroy( p_currList );
+ cl_free (p_currList);
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "__updn_bfs_by_node:"
+ "BFS the subnet ]\n");
+ OSM_LOG_EXIT( &(osm.log));
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+updn_destroy(
+ IN updn_t* const p_updn )
+{
+ cl_map_item_t *p_map_item;
+ uint64_t *p_guid_list_item;
+
+ /* Destroy the updn struct */
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+ {
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_subn_calc_up_down_min_hop_table : "
+ "guid = 0x%" PRIx64 " rank = %u\n",
+ cl_ntoh64(cl_qmap_key(p_map_item)), ((updn_rank_t *)p_map_item)->rank);
+ cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+ cl_free( (updn_rank_t *)p_map_item);
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ }
+
+ /* free the array of guids */
+ if (p_updn->updn_ucast_reg_inputs.guid_list)
+ cl_free(p_updn->updn_ucast_reg_inputs.guid_list);
+
+ /* destroy the list of root nodes */
+ while ((p_guid_list_item = cl_list_remove_head( p_updn->p_root_nodes )))
+ cl_free( p_guid_list_item );
+
+ cl_list_remove_all( p_updn->p_root_nodes );
+ cl_list_destroy( p_updn->p_root_nodes );
+ cl_free ( p_updn->p_root_nodes );
+ cl_free (p_updn);
+}
+
+updn_t*
+updn_construct(void)
+{
+ updn_t* p_updn;
+
+ OSM_LOG_ENTER( &(osm.log) , updn_construct);
+
+ p_updn = cl_zalloc(sizeof(updn_t));
+ if (p_updn == NULL)
+ {
+ goto Exit;
+ }
+ Exit :
+ OSM_LOG_EXIT( &(osm.log) );
+ return(p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+updn_init(
+ IN updn_t* const p_updn )
+{
+ cl_list_t * p_list;
+ FILE* p_updn_guid_file;
+ char line[MAX_UPDN_GUID_FILE_LINE_LENGTH];
+ uint64_t * p_tmp;
+ cl_list_iterator_t guid_iterator;
+ ib_api_status_t status = IB_SUCCESS;
+
+
+ OSM_LOG_ENTER( &(osm.log) , updn_init );
+ p_updn->state = UPDN_INIT;
+ cl_qmap_init( &p_updn->guid_rank_tbl);
+ p_list = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ if (!p_list)
+ {
+ status = IB_ERROR;
+ goto Exit_Bad;
+ }
+ cl_list_construct( p_list );
+ cl_list_init( p_list, 10 );
+ p_updn->p_root_nodes = p_list;
+ p_updn->updn_ucast_reg_inputs.num_guids = 0;
+ p_updn->updn_ucast_reg_inputs.guid_list = NULL;
+ p_updn->auto_detect_root_nodes = FALSE;
+ /* Check if updn is activated , then fetch root nodes */
+ if (osm.subn.opt.updn_activate)
+ {
+ /*
+ Check the source for root node list, if file parse it, otherwise
+ wait for a callback to activate auto detection
+ */
+ if (osm.subn.opt.updn_guid_file)
+ {
+ /* Now parse guid from file */
+ p_updn_guid_file = fopen(osm.subn.opt.updn_guid_file, "r");
+ if (p_updn_guid_file == NULL)
+ {
+ osm_log( &osm.log, OSM_LOG_ERROR,
+ "osm_opensm_init : ERR AA02: "
+ "Fail to open guid list file (%s).\n",
+ osm.subn.opt.updn_guid_file);
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+
+ while ( fgets(line,MAX_UPDN_GUID_FILE_LINE_LENGTH, p_updn_guid_file) )
+ {
+ if (strcspn(line, " ,;.") == strlen(line))
+ {
+ /* Skip Empty Lines anywhere in the file - only one char means the Null termination */
+ if (strlen(line) > 1)
+ {
+ p_tmp = cl_malloc(sizeof(uint64_t));
+ *p_tmp = strtoull(line,NULL,16);
+ cl_list_insert_tail(osm.p_updn_ucast_routing->p_root_nodes, p_tmp);
+ }
+ }
+ else
+ {
+ osm_log( &osm.log, OSM_LOG_ERROR,
+ "osm_opensm_init : ERR AA03: "
+ "Bad formatted guid in file (%s) : %s.\n"
+ , osm.subn.opt.updn_guid_file,line);
+ status = IB_NOT_FOUND;
+ break;
+ }
+ }
+
+ /* For Debug Purposes ... */
+ osm_log( &osm.log, OSM_LOG_DEBUG,
+ "osm_opensm_init : "
+ "UPDN - Root nodes fetching by file %s.\n",
+ osm.subn.opt.updn_guid_file);
+ guid_iterator = cl_list_head(osm.p_updn_ucast_routing->p_root_nodes);
+ while( guid_iterator != cl_list_end(osm.p_updn_ucast_routing->p_root_nodes) )
+ {
+ osm_log( &osm.log, OSM_LOG_DEBUG,
+ "osm_opensm_init : "
+ "Inserting guid 0x%" PRIx64 " as root node.\n",
+ *((uint64_t*)cl_list_obj(guid_iterator)) );
+ guid_iterator = cl_list_next(guid_iterator);
+ }
+ }
+ else
+ {
+ osm.p_updn_ucast_routing->auto_detect_root_nodes = TRUE;
+ }
+ /* If auto mode detection reuired - will be executed in main b4 the assignment of UI Ucast */
+ }
+
+ goto Exit;
+
+ Exit_Bad :
+ return 1;
+ Exit :
+ OSM_LOG_EXIT( &(osm.log) );
+ return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* NOTE : PLS check if we need to decide that the first */
+/* rank is a SWITCH for BFS purpose */
+int
+updn_subn_rank(
+ IN uint64_t root_guid,
+ IN uint8_t base_rank,
+ IN updn_t* p_updn)
+{
+ /* Init local vars */
+ osm_port_t *p_root_port=NULL;
+ uint16_t tbl_size;
+ uint8_t rank=base_rank;
+ osm_physp_t *p_physp, *p_remote_physp,*p_physp_temp;
+ cl_list_t *p_currList,*p_nextList;
+ cl_status_t did_cause_update;
+ uint8_t num_ports,port_num;
+
+ OSM_LOG_ENTER( &(osm.log) , updn_subn_rank);
+
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Ranking Starts from guid 0x%" PRIx64 "\n", root_guid);
+
+ /* Init the list pointers */
+ p_nextList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_currList = p_nextList;
+
+ /* Check valid subnet & guid */
+ tbl_size = (uint16_t)(cl_qmap_count(&(osm.subn.port_guid_tbl)));
+ if (tbl_size == 0)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "updn_subn_rank: ERR AA04: "
+ "Port guid table is empty, cannot perform ranking.\n");
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+
+ p_root_port = (osm_port_t*) cl_qmap_get(&(osm.subn.port_guid_tbl), \
+ cl_ntoh64(root_guid));
+ if( p_root_port == (osm_port_t*)cl_qmap_end( &(osm.subn.port_guid_tbl) ) )
+ {
+
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "updn_subn_rank: ERR AA05: "
+ "Wrong guid value : 0x%" PRIx64 ".\n", root_guid);
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+
+ /* Rank the first chosen guid anyway since its the base rank */
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Ranking port guid 0x%" PRIx64 ".\n",root_guid);
+
+ __updn_update_rank(&p_updn->guid_rank_tbl, cl_ntoh64(root_guid), rank);
+ /*
+ HACK: We are assuming SM is running on HCA, so when getting the default
+ port we'll get the port connected to the rest of the subnet. If SM is
+ running on SWITCH - we should try to get a dr path from all switch ports.
+ */
+ p_physp = osm_port_get_default_phys_ptr( p_root_port );
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ /* We can safely add the node to the list */
+ cl_list_insert_tail(p_nextList, p_physp);
+ /* Assign pointer to the list for BFS */
+ p_currList = p_nextList;
+
+
+ /* BFS the list till its empty */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "BFS the subnet [\n");
+
+ while (!cl_is_list_empty(p_currList))
+ {
+ rank++;
+ p_nextList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+ /* Go over all remote nodes and rank them (if not allready visited) till
+ no elemtent in the list p_currList */
+ while ( p_physp != NULL )
+ {
+ num_ports = osm_node_get_num_physp( p_physp->p_node );
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Handling port guid 0x%" PRIx64 "\n", cl_ntoh64(p_physp->port_guid));
+ for (port_num = 1 ; port_num < num_ports ; port_num++)
+ {
+ ib_net64_t port_guid;
+
+ /* Current port fetched in order to get remote side */
+ p_physp_temp = osm_node_get_physp_ptr( p_physp->p_node, port_num );
+ p_remote_physp = p_physp_temp->p_remote_physp;
+
+ /*
+ make sure that all the following occure on p_remote_physp:
+ 1. The port isn't NULL
+ 2. The port is a valid port
+ */
+ if ( p_remote_physp &&
+ osm_physp_is_valid ( p_remote_physp ))
+ {
+ port_guid = p_remote_physp->port_guid;
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Visiting remote port guid 0x%" PRIx64 "\n"
+ , cl_ntoh64(port_guid));
+ /* Was it visited ?
+ Only if the pointer equal to cl_qmap_end its not
+ found in the list */
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Ranking port guid 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+ did_cause_update = __updn_update_rank(&p_updn->guid_rank_tbl, port_guid, rank);
+
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Rank of port guid 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid),
+ ((updn_rank_t*)cl_qmap_get(&p_updn->guid_rank_tbl, port_guid))->rank
+ );
+
+ if (did_cause_update)
+ {
+ cl_list_insert_tail(p_nextList, p_remote_physp);
+ }
+ }
+ }
+ /* Propagte through the next item in the p_currList */
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+ }
+ /* First free the allocation of cl_list pointer then reallocate */
+ cl_list_destroy( p_currList );
+ cl_free(p_currList);
+ /* p_currList is empty - need to assign it to p_nextList */
+ p_currList = p_nextList;
+ }
+
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "BFS the subnet ]\n");
+
+ cl_list_destroy( p_currList );
+ cl_free(p_currList);
+
+ /* Print Summary of ranking */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Rank Info :\n\t Root Guid = 0x%" PRIx64 "\n\t Max Node Rank = %d\n"
+ , cl_ntoh64(p_root_port->guid),rank);
+ p_updn->state = UPDN_RANK;
+ OSM_LOG_EXIT( &(osm.log));
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+int
+osm_subn_set_up_down_min_hop_table(
+ IN updn_t* p_updn)
+{
+ /* Init local vars */
+ osm_subn_t *p_subn = &(osm.subn);
+ osm_switch_t *p_next_sw,*p_sw;
+ osm_port_t *p_next_port,*p_port;
+ ib_net64_t port_guid;
+
+ OSM_LOG_ENTER( &(osm.log) , osm_subn_set_up_down_min_hop_table );
+ if (p_updn->state == UPDN_INIT)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "osm_subn_set_up_down_min_hop_table: ERR AA06: "
+ "Calculating Min Hop only allowed after Ranking\n");
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+
+ /* Check if its a non switched subnet .. */
+ if ( cl_is_qmap_empty( &p_subn->sw_guid_tbl ) )
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "osm_subn_set_up_down_min_hop_table: ERR AA10: "
+ "This is a non switched subnet , cannot perform Algorithm\n");
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+ /* Go over all the switches in the subnet - for each init their Min Hop
+ Table */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "osm_subn_set_up_down_min_hop_table:"
+ "Init Min Hop Table of all switches [\n");
+
+ p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl );
+ while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) )
+ {
+ uint16_t max_lid_ho,lid_ho;
+
+ p_sw = p_next_sw;
+ p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ /* Clear Min Hop Table && FWD Tbls - This should caused opensm to
+ rebuild its FWD tables , post setting Min Hop Tables */
+ osm_lid_matrix_clear(&(p_sw->lmx));
+ max_lid_ho = osm_switch_get_max_lid_ho(p_sw);
+ for (lid_ho=1 ; lid_ho <= max_lid_ho ; lid_ho++)
+ osm_switch_set_path(p_sw,lid_ho,OSM_NO_PATH,TRUE);
+ }
+
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "osm_subn_set_up_down_min_hop_table:"
+ "Init Min Hop Table of all switches ]\n");
+
+ /* Now do the BFS for each port in the subnet */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "osm_subn_set_up_down_min_hop_table:"
+ "BFS through all port guids in the subnet [\n");
+ p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl );
+ while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) )
+ {
+ p_port = p_next_port;
+ p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+ port_guid = cl_qmap_key(&(p_port->map_item));
+ osm_log(&(osm.log), OSM_LOG_DEBUG,
+ "BFS through port guid 0x%" PRIx64 ".\n"
+ , cl_ntoh64(port_guid));
+ if(__updn_bfs_by_node(p_subn,port_guid,
+ &p_updn->guid_rank_tbl))
+ {
+ OSM_LOG_EXIT( &(osm.log));
+ return 1;
+ }
+ }
+
+ osm_log(&(osm.log), OSM_LOG_INFO,
+ "osm_subn_set_up_down_min_hop_table:"
+ "BFS through all port guids in the subnet ]\n");
+ /* Cleanup */
+ OSM_LOG_EXIT( &(osm.log));
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+int
+osm_subn_calc_up_down_min_hop_table(
+ IN uint32_t num_guids,
+ IN uint64_t * guid_list,
+ IN updn_t* p_updn)
+{
+ uint8_t idx=0;
+ cl_map_item_t *p_map_item;
+ int status;
+
+ OSM_LOG_ENTER( &(osm.log) , osm_subn_calc_up_down_min_hop_table );
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "osm_subn_calc_up_down_min_hop_table :"
+ "Ranking all port guids in the list\n");
+ if (num_guids == 0)
+ {
+ osm_log(&(osm.log), OSM_LOG_ERROR,
+ "osm_subn_calc_up_down_min_hop_table :"
+ "No guids were given or number of guids is 0\n");
+ return 1;
+ }
+
+ for (idx=0;idx < num_guids;idx++)
+ {
+ /* Apply the ranking for each guid given by user - bypass illegal ones */
+ updn_subn_rank(guid_list[idx], 0, p_updn);
+ }
+ /* After multiple ranking need to set Min Hop Table by UpDn algorithm */
+ osm_log(&(osm.log), OSM_LOG_VERBOSE,
+ "osm_subn_calc_up_down_min_hop_table :"
+ "Setting all switches' Min Hop Table\n");
+
+ status = osm_subn_set_up_down_min_hop_table (p_updn);
+
+ /* Cleanup updn rank tbl */
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+ {
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_subn_calc_up_down_min_hop_table : "
+ "guid = 0x%" PRIx64 " rank = %u\n",
+ cl_ntoh64(cl_qmap_key(p_map_item)), ((updn_rank_t *)p_map_item)->rank);
+ cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+ cl_free( (updn_rank_t *)p_map_item);
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ }
+
+ OSM_LOG_EXIT( &(osm.log));
+ return status;
+
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN callback function */
+
+int __osm_updn_call( void *ctx) {
+ OSM_LOG_ENTER(&(osm.log), __osm_updn_call);
+ /* First auto detect root nodes - if required */
+ if ( ((updn_t*)ctx)->auto_detect_root_nodes )
+ {
+ /* printf ("-V- b4 osm_updn_find_root_nodes_by_min_hop\n");*/
+ osm_updn_find_root_nodes_by_min_hop( ((updn_t*)ctx) );
+ }
+ /* printf ("-V- after osm_updn_find_root_nodes_by_min_hop\n"); */
+ /* Only if there are assigned root nodes do the algorithm , otherwise perform do nothing */
+ if ( ((updn_t*)ctx)->updn_ucast_reg_inputs.num_guids > 0)
+ {
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "__osm_updn_call : "
+ "activating UPDN algorithm.\n");
+ osm_subn_calc_up_down_min_hop_table( ((updn_t*)ctx)->updn_ucast_reg_inputs.num_guids,
+ ((updn_t*)ctx)->updn_ucast_reg_inputs.guid_list
+ , ((updn_t*)ctx) );
+ }
+ else
+ osm_log (&(osm.log), OSM_LOG_INFO,
+ "__osm_updn_call : "
+ "disable UPDN algorithm , no root nodes were found.\n");
+
+ OSM_LOG_EXIT(&(osm.log));
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN convert cl_list to guid array in updn struct */
+void __osm_updn_convert_list2array (IN updn_t * p_updn) {
+ uint32_t i = 0,max_num = 0;
+ uint64_t * p_guid;
+
+ OSM_LOG_ENTER(&(osm.log), __osm_updn_convert_list2array);
+ p_updn->updn_ucast_reg_inputs.num_guids = cl_list_count(
+ p_updn->p_root_nodes);
+ if (p_updn->updn_ucast_reg_inputs.guid_list)
+ cl_free(p_updn->updn_ucast_reg_inputs.guid_list);
+ p_updn->updn_ucast_reg_inputs.guid_list = (uint64_t *)cl_zalloc(
+ p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t));
+ if (!cl_is_list_empty(p_updn->p_root_nodes))
+ {
+ ;
+ while( (p_guid = (uint64_t*)cl_list_remove_head(p_updn->p_root_nodes)) )
+ {
+ p_updn->updn_ucast_reg_inputs.guid_list[i] = *p_guid;
+ cl_free(p_guid);
+ i++;
+ }
+ max_num = i;
+ for (i=0;i < max_num ; i++ )
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "__osm_updn_convert_list2array : "
+ "Map guid 0x%" PRIx64 " into UPDN array.\n",
+ p_updn->updn_ucast_reg_inputs.guid_list[i]);
+ }
+ /* Since we need the template list for other sweeps, we wont destroy & free it */
+ OSM_LOG_EXIT(&(osm.log));
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Registration function to ucast routing manager (instead of
+ Min Hop Algorithm) */
+
+int
+osm_updn_reg_calc_min_hop_table(
+ IN updn_t * p_updn,
+ IN osm_subn_opt_t* p_opt )
+{
+ OSM_LOG_ENTER(&(osm.log), osm_updn_reg_calc_min_hop_table);
+ /*
+ If root nodes were supplied by the user - we need to convert into array
+ otherwise, will be created & converted in callback function activation
+ */
+ if (!p_updn->auto_detect_root_nodes)
+ {
+ __osm_updn_convert_list2array(p_updn);
+ }
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_reg_calc_min_hop_table : "
+ "assigning ucast fdb UI function with updn callback\n");
+ p_opt->pfn_ui_ucast_fdb_assign = __osm_updn_call;
+ p_opt->ui_ucast_fdb_assign_ctx = (void *)p_updn;
+ OSM_LOG_EXIT(&(osm.log));
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Find Root nodes automatically by Min Hop Table info */
+int
+osm_updn_find_root_nodes_by_min_hop( OUT updn_t * p_updn )
+{
+ osm_switch_t *p_next_sw,*p_sw;
+ osm_port_t *p_next_port,*p_port;
+ osm_physp_t *p_physp;
+ uint32_t numCas = 0;
+ uint32_t numSws = cl_qmap_count(&osm.subn.sw_guid_tbl);
+ cl_qmap_t min_hop_hist; /* Histogram container */
+ updn_hist_t *p_updn_hist,*p_up_ht;
+ uint8_t maxHops = 0; /* contain the max histogram index */
+ uint64_t *p_guid;
+ cl_list_t *p_root_nodes_list = p_updn->p_root_nodes;
+ cl_map_t ca_by_lid_map; /* map holding all CA lids */
+ uint16_t self_lid_ho;
+
+ OSM_LOG_ENTER(&(osm.log), osm_updn_find_root_nodes_by_min_hop);
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "current number of ports in the subnet is %d.\n",
+ cl_qmap_count(&osm.subn.port_guid_tbl));
+ /* Init the required vars */
+ cl_qmap_init( &min_hop_hist );
+ cl_map_construct( &ca_by_lid_map );
+ cl_map_init( &ca_by_lid_map, 10 );
+
+ /* EZ:
+ p_ca_list = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+ cl_list_construct( p_ca_list );
+ cl_list_init( p_ca_list, 10 );
+ */
+
+ /* Find the Maximum number of Cas for `histogram normalization */
+ osm_log (&(osm.log), OSM_LOG_VERBOSE,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Find the number of CA and store them in cl_list.\n");
+ p_next_port = (osm_port_t*)cl_qmap_head( &osm.subn.port_guid_tbl );
+ while( p_next_port != (osm_port_t*)cl_qmap_end( &osm.subn.port_guid_tbl ) ) {
+ p_port = p_next_port;
+ p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item );
+ if ( osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_CA )
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ self_lid_ho = cl_ntoh16( osm_physp_get_base_lid(p_physp) );
+ numCas++;
+ /* EZ:
+ self = cl_malloc(sizeof(uint16_t));
+ *self = self_lid_ho;
+ cl_list_insert_tail(p_ca_list, self);
+ */
+ cl_map_insert( &ca_by_lid_map, self_lid_ho, (void *)0x1);
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Inserting into array guid 0x%" PRIx64 " , Lid : 0x%x.\n",
+ cl_ntoh64(osm_port_get_guid(p_port)), self_lid_ho);
+ }
+ }
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Found %u CA , %u SW in the subnet .\n", numCas,numSws);
+ p_next_sw = (osm_switch_t*)cl_qmap_head( &osm.subn.sw_guid_tbl );
+ osm_log (&(osm.log), OSM_LOG_VERBOSE,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Passing through all switches to collect Min Hop Info.\n");
+ while( p_next_sw != (osm_switch_t*)cl_qmap_end( &osm.subn.sw_guid_tbl ) )
+ {
+ uint16_t max_lid_ho,lid_ho;
+ uint8_t hop_val;
+ uint16_t numHopBarsOverThd1 = 0;
+ uint16_t numHopBarsOverThd2 = 0;
+ double thd1,thd2;
+
+ p_sw = p_next_sw;
+ /* Roll to the next switch */
+ p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+
+ /* Clear Min Hop Table && FWD Tbls - This should caused opensm to
+ rebuild its FWD tables , post setting Min Hop Tables */
+ max_lid_ho = osm_switch_get_max_lid_ho(p_sw);
+ /* Get base lid of switch by retrieving port 0 lid of node pointer */
+ self_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_sw->p_node, 0 ) );
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Passing through switch lid 0x%x.\n", self_lid_ho);
+ for (lid_ho=1 ; lid_ho <= max_lid_ho ; lid_ho++)
+ {
+ /* Skip lids which are not CAs -
+ for the histogram purposes we care only about CAs */
+
+ /* EZ:
+ boolean_t LidFound = FALSE;
+ cl_list_iterator_t ca_lid_iterator= cl_list_head(p_ca_list);
+ while( (ca_lid_iterator != cl_list_end(p_ca_list)) && !LidFound )
+ {
+ uint16_t *p_lid;
+
+ p_lid = (uint16_t*)cl_list_obj(ca_lid_iterator);
+ if ( *p_lid == lid_ho )
+ LidFound = TRUE;
+ ca_lid_iterator = cl_list_next(ca_lid_iterator);
+
+ }
+ if ( LidFound )
+ */
+ if (cl_map_get( &ca_by_lid_map, lid_ho ))
+ {
+ hop_val = osm_switch_get_least_hops( p_sw, lid_ho );
+ if (hop_val > maxHops)
+ maxHops = hop_val;
+ p_updn_hist =
+ (updn_hist_t*)cl_qmap_get( &min_hop_hist , (uint64_t)hop_val );
+ if ( p_updn_hist == (updn_hist_t*)cl_qmap_end( &min_hop_hist))
+ {
+ /* New entry in the histogram , first create it */
+ p_updn_hist = (updn_hist_t*) cl_malloc(sizeof(updn_hist_t));
+ CL_ASSERT (p_updn_hist);
+ p_updn_hist->bar_value = 1;
+ cl_qmap_insert(&min_hop_hist, (uint64_t)hop_val, &p_updn_hist->map_item);
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Creating new entry in histogram %u with bar value 1.\n",
+ hop_val);
+ }
+ else
+ {
+ /* Entry exist in the table , just increment the value */
+ p_updn_hist->bar_value++;
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Updating entry in histogram %u with bar value %d.\n", hop_val,
+ p_updn_hist->bar_value);
+ }
+ }
+ }
+
+ /* Now recognize the spines by requiring one bar to be above 90% of the
+ number of CAs */
+ thd1 = numCas * 0.9;
+ thd2 = numCas * 0.05;
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Pass over the histogram value and find only one root node above "
+ "thd1 = %f && thd2 = %f.\n", thd1, thd2);
+
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ while( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+ {
+ p_up_ht = p_updn_hist;
+ p_updn_hist = (updn_hist_t*)cl_qmap_next( &p_updn_hist->map_item ) ;
+ if ( p_up_ht->bar_value > thd1 )
+ numHopBarsOverThd1++;
+ if ( p_up_ht->bar_value > thd2 )
+ numHopBarsOverThd2++;
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Passing through histogram - Hop Index %u : "
+ "numHopBarsOverThd1 = %u , numHopBarsOverThd2 = %u.\n",
+ (uint16_t)cl_qmap_key((cl_map_item_t*)p_up_ht), numHopBarsOverThd1 ,
+ numHopBarsOverThd2);
+ }
+
+ /* destroy the qmap table and all its content - no longer needed */
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Cleanup : delete histogram "
+ "UPDN - Root nodes fetching by auto detect.\n");
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ while ( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+ {
+ cl_qmap_remove_item( &min_hop_hist, (cl_map_item_t*)p_updn_hist );
+ cl_free( p_updn_hist );
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ }
+
+ /* If thd conditions are valid insert the root node to the list */
+ if ( (numHopBarsOverThd1 == 1) && (numHopBarsOverThd2 == 1) )
+ {
+ p_guid = cl_malloc(sizeof(uint64_t));
+ *p_guid = cl_ntoh64(osm_node_get_node_guid(p_sw->p_node));
+ osm_log (&(osm.log), OSM_LOG_DEBUG,
+ "osm_updn_find_root_nodes_by_min_hop : "
+ "Inserting guid 0x%" PRIx64 " as root node.\n",
+ *p_guid);
+ cl_list_insert_tail(p_root_nodes_list, p_guid);
+ }
+ }
+
+ /* destroy the map of CA lids */
+ cl_map_remove_all( &ca_by_lid_map );
+ cl_map_destroy( &ca_by_lid_map );
+
+ /* Now convert the cl_list to array */
+ __osm_updn_convert_list2array(p_updn);
+
+ OSM_LOG_EXIT(&(osm.log));
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vl15_t.
+ * This object represents the VL15 Interface object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+ Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_signal_osd.h>
+#include <complib/cl_memory.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vl15_poller(
+ IN void *p_ptr )
+{
+ ib_api_status_t status;
+ osm_madw_t *p_madw;
+ uint32_t mads_sent;
+ uint32_t unicasts_sent;
+ uint32_t mads_on_wire;
+ osm_vl15_t* const p_vl = (osm_vl15_t*)p_ptr;
+ cl_qlist_t* p_fifo;
+
+ OSM_LOG_ENTER( p_vl->p_log, __osm_vl15_poller );
+
+ if ( p_vl->thread_state == OSM_THREAD_STATE_NONE)
+ {
+ cl_sig_mask_sigint();
+ p_vl->thread_state = OSM_THREAD_STATE_RUN;
+ }
+
+ while( p_vl->thread_state == OSM_THREAD_STATE_RUN )
+ {
+ /*
+ Start servicing the FIFOs by pulling off MAD wrappers
+ and passing them to the transport interface.
+ There are lots of corner cases here so tread carefully.
+
+ The unicast FIFO has priority, since somebody is waiting
+ for a timely response.
+ */
+ cl_spinlock_acquire( &p_vl->lock );
+
+ if( cl_qlist_count( &p_vl->ufifo ) != 0 )
+ p_fifo = &p_vl->ufifo;
+ else
+ p_fifo = &p_vl->rfifo;
+
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( p_fifo );
+
+ cl_spinlock_release( &p_vl->lock );
+
+ if( p_madw != (osm_madw_t*)cl_qlist_end( p_fifo ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "Servicing p_madw = %p.\n", p_madw );
+ }
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_FRAMES ) )
+ {
+ osm_dump_dr_smp( p_vl->p_log,
+ osm_madw_get_smp_ptr( p_madw ), OSM_LOG_FRAMES );
+ }
+
+ /*
+ Non-response-expected mads are not throttled on the wire
+ since we can have no confirmation that they arrived
+ at their destination.
+ */
+ if( p_madw->resp_expected == TRUE )
+ {
+ /*
+ Note that other threads may not see the response MAD
+ arrive before send() even returns.
+ In that case, the wire count would temporarily go negative.
+ To avoid this confusion, preincrement the counts on the
+ assumption that send() will succeed.
+ */
+ mads_on_wire = cl_atomic_inc(
+ &p_vl->p_stats->qp0_mads_outstanding_on_wire );
+ CL_ASSERT( mads_on_wire <= p_vl->max_wire_smps );
+ }
+ else
+ {
+ unicasts_sent = cl_atomic_inc(
+ &p_vl->p_stats->qp0_unicasts_sent );
+ }
+
+ mads_sent = cl_atomic_inc( &p_vl->p_stats->qp0_mads_sent );
+
+ status = osm_vendor_send(
+ osm_madw_get_bind_handle( p_madw ),
+ p_madw, p_madw->resp_expected );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_ERROR,
+ "__osm_vl15_poller: ERR 3E03: "
+ "MAD send failed (%s).\n",
+ ib_get_err_str( status ) );
+
+ /*
+ The MAD was never successfully sent, so
+ Fix-up the pre-incremented count values.
+ */
+ mads_sent = cl_atomic_dec( &p_vl->p_stats->qp0_mads_sent );
+ }
+ else
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "%u on wire, %u outstanding, %u unicasts sent, "
+ "%u sent total.\n",
+ p_vl->p_stats->qp0_mads_outstanding_on_wire,
+ p_vl->p_stats->qp0_mads_outstanding,
+ p_vl->p_stats->qp0_unicasts_sent,
+ p_vl->p_stats->qp0_mads_sent );
+ }
+ }
+ }
+ else
+ {
+ /*
+ The VL15 FIFO is empty, so we have nothing left to do.
+ */
+ status = cl_event_wait_on( &p_vl->signal,
+ EVENT_NO_TIMEOUT, TRUE );
+ }
+
+ while( (p_vl->p_stats->qp0_mads_outstanding_on_wire >=
+ (int32_t)p_vl->max_wire_smps ) &&
+ (p_vl->thread_state == OSM_THREAD_STATE_RUN ) )
+ {
+ status = cl_event_wait_on( &p_vl->signal,
+ EVENT_NO_TIMEOUT, TRUE );
+ }
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_ERROR,
+ "__osm_vl15_poller: ERR 3E02: "
+ "Event wait failed (%s).\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+
+ /*
+ since we abort immediately when the state != OSM_THREAD_STATE_RUN
+ we might have some mads on the queues. After the thread exits
+ the vl15 destroy should put back these mads...
+ */
+
+ OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_construct(
+ IN osm_vl15_t* const p_vl )
+{
+ cl_memclr( p_vl, sizeof(*p_vl) );
+ p_vl->state = OSM_VL15_STATE_INIT;
+ p_vl->thread_state = OSM_THREAD_STATE_NONE;
+ cl_event_construct( &p_vl->signal );
+ cl_spinlock_construct( &p_vl->lock );
+ cl_qlist_init( &p_vl->rfifo );
+ cl_qlist_init( &p_vl->ufifo );
+ cl_thread_construct( &p_vl->poller );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_destroy(
+ IN osm_vl15_t* const p_vl,
+ IN struct _osm_mad_pool *p_pool)
+{
+ osm_madw_t* p_madw;
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_destroy );
+
+ /*
+ Signal our threads that we're leaving.
+ */
+ p_vl->thread_state = OSM_THREAD_STATE_EXIT;
+
+ /*
+ Don't trigger unless event has been initialized.
+ Destroy the thread before we tear down the other objects.
+ */
+ if( p_vl->state != OSM_VL15_STATE_INIT )
+ cl_event_signal( &p_vl->signal );
+
+ cl_thread_destroy( &p_vl->poller );
+
+ /*
+ Return the outstanding messages to the pool
+ */
+
+ cl_spinlock_acquire( &p_vl->lock );
+
+ while (!cl_is_qlist_empty( &p_vl->rfifo))
+ {
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo);
+ osm_mad_pool_put( p_pool, p_madw );
+ }
+ while (!cl_is_qlist_empty( &p_vl->ufifo))
+ {
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo);
+ osm_mad_pool_put( p_pool, p_madw );
+ }
+
+ cl_spinlock_release( &p_vl->lock );
+
+ cl_event_destroy( &p_vl->signal );
+ p_vl->state = OSM_VL15_STATE_INIT;
+ cl_spinlock_destroy( &p_vl->lock );
+
+ OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vl15_init(
+ IN osm_vl15_t* const p_vl,
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN const int32_t max_wire_smps )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_vl15_init );
+
+ p_vl->p_vend = p_vend;
+ p_vl->p_log = p_log;
+ p_vl->p_stats = p_stats;
+ p_vl->max_wire_smps = max_wire_smps;
+
+ status = cl_event_init( &p_vl->signal, FALSE );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ p_vl->state = OSM_VL15_STATE_READY;
+
+ status = cl_spinlock_init( &p_vl->lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ /*
+ Initialize the thread after all other dependent objects
+ have been initialized.
+ */
+ status = cl_thread_init( &p_vl->poller, __osm_vl15_poller, p_vl,
+ "opensm poller" );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_poll(
+ IN osm_vl15_t* const p_vl )
+{
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_poll );
+
+ CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+ /*
+ If we have room for more VL15 MADs on the wire,
+ then signal the poller thread.
+
+ This is not an airtight check, since the poller thread
+ could be just about to send another MAD as we signal
+ the event here. To cover this rare case, the poller
+ thread checks for a spurious wake-up.
+ */
+ if( p_vl->p_stats->qp0_mads_outstanding_on_wire <
+ (int32_t)p_vl->max_wire_smps )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_poll: "
+ "Signalling poller thread.\n" );
+ }
+
+ cl_event_signal( &p_vl->signal );
+ }
+
+ OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_post(
+ IN osm_vl15_t* const p_vl,
+ IN osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_post );
+
+ CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_post: "
+ "Posting p_madw = 0x%p.\n", p_madw );
+ }
+
+ /*
+ Determine in which fifo to place the pending madw.
+ */
+ cl_spinlock_acquire( &p_vl->lock );
+ if( p_madw->resp_expected == TRUE )
+ {
+ cl_qlist_insert_tail( &p_vl->rfifo, (cl_list_item_t*)p_madw );
+ cl_atomic_inc( &p_vl->p_stats->qp0_mads_outstanding );
+ }
+ else
+ {
+ cl_qlist_insert_tail( &p_vl->ufifo, (cl_list_item_t*)p_madw );
+ }
+ cl_spinlock_release( &p_vl->lock );
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_post: "
+ "%u MADs on wire, %u MADs outstanding.\n",
+ p_vl->p_stats->qp0_mads_outstanding_on_wire,
+ p_vl->p_stats->qp0_mads_outstanding );
+ }
+
+ osm_vl15_poll( p_vl );
+
+ OSM_LOG_EXIT( p_vl->p_log );
+
+}
+
+void
+osm_vl15_shutdown(
+ IN osm_vl15_t* const p_vl,
+ IN osm_mad_pool_t* const p_mad_pool)
+{
+ osm_madw_t* p_madw;
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_shutdown );
+
+ /* we only should get here after the VL15 interface was initialized */
+ CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+ /* grap a lock on the object */
+ cl_spinlock_acquire( &p_vl->lock );
+
+ /* go over all outstanding MADs and retire their transactions */
+
+ /* first we handle the list of response MADs */
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo );
+ while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->ufifo ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_shutdown: "
+ "Releasing Response p_madw = %p.\n", p_madw );
+ }
+
+ osm_mad_pool_put( p_mad_pool, p_madw );
+ cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo );
+ }
+
+ /* Request MADs we send out */
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo );
+ while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->rfifo ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_shutdown: "
+ "Releasing Request p_madw = %p.\n", p_madw );
+ }
+
+ osm_mad_pool_put( p_mad_pool, p_madw );
+ cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+ p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo );
+ }
+
+ /* free the lock */
+ cl_spinlock_release( &p_vl->lock );
+ OSM_LOG_EXIT( p_vl->p_log );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vla_rcv_t.
+ * This object represents the Vl Arbitration Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_vl_arb_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_construct(
+ IN osm_vla_rcv_t* const p_rcv )
+{
+ cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_destroy(
+ IN osm_vla_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_init(
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_vla_rcv_init );
+
+ osm_vla_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+void
+osm_vla_rcv_process(
+ IN const osm_vla_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_vl_arb_table_t *p_vla_tbl;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ osm_vla_context_t *p_context;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t port_num, block_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ p_context = osm_madw_get_vla_context_ptr( p_madw );
+ p_vla_tbl = (ib_vl_arb_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+ port_guid = p_context->port_guid;
+ node_guid = p_context->node_guid;
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_VL_ARBITRATION );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: ERR 3F06: "
+ "No Port object for port with GUID = 0x%" PRIx64
+ "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ goto Exit;
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ block_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) >> 16);
+ /* in case of a non switch node the attr modifier should be ignored */
+ if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+ {
+ port_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) & 0x000000FF);
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ }
+ else
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ port_num = p_port->default_port_num;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to update
+ the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_vla_rcv_process: "
+ "Got GetResp(VLArb) block:%u port_num %u with GUID = 0x%" PRIx64
+ " for parent node GUID = 0x%" PRIx64
+ ", TID = 0x%" PRIx64 ".\n",
+ block_num, port_num,
+ cl_ntoh64( port_guid ),
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ /*
+ Determine if we encountered a new Physical Port.
+ If so, Ignore it.
+ */
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: "
+ "Got invalid port number 0x%X.\n",
+ port_num );
+ }
+ goto Exit;
+ }
+
+ osm_dump_vl_arb_table( p_rcv->p_log,
+ port_guid, block_num,
+ port_num, p_vla_tbl,
+ OSM_LOG_DEBUG );
+
+ if ( (block_num < 1) || (block_num > 4) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: "
+ "Got invalid block number 0x%X. \n",
+ block_num );
+ goto Exit;
+ }
+ osm_physp_set_vla_tbl( p_physp, p_vla_tbl, block_num);
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vla_rcv_ctrl_t.
+ * This object represents the Vl Arbitration request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/*
+ Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vla_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_vla_rcv_process( ((osm_vla_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_construct(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+ cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_destroy(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_ctrl_init(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl,
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vla_rcv_ctrl_init );
+
+ osm_vla_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_VL_ARB,
+ __osm_vla_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_ctrl_init: ERR 4001: "
+ "Dispatcher registration failed.\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/st.h>
+
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+typedef struct st_table_entry st_table_entry;
+
+struct st_table_entry {
+ unsigned int hash;
+ st_data_t key;
+ st_data_t record;
+ st_table_entry *next;
+};
+
+#define ST_DEFAULT_MAX_DENSITY 5
+#define ST_DEFAULT_INIT_TABLE_SIZE 11
+
+/*
+ * DEFAULT_MAX_DENSITY is the default for the largest we allow the
+ * average number of items per bin before increasing the number of
+ * bins
+ *
+ * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
+ * allocated initially
+ *
+ */
+static int numcmp(void *, void *);
+static st_ptr_t numhash(void *);
+static struct st_hash_type type_numhash = {
+ numcmp,
+ numhash,
+};
+
+
+/* extern int strcmp(const char *, const char *); */
+static int strhash(const char *);
+
+static inline st_ptr_t st_strhash(void *key)
+{
+ return strhash((const char *)key);
+}
+
+static inline int st_strcmp(void *key1, void *key2)
+{
+ return strcmp((const char *)key1, (const char *)key2);
+}
+
+static struct st_hash_type type_strhash = {
+ st_strcmp,
+ st_strhash
+};
+
+
+#define xmalloc malloc
+#define xcalloc calloc
+#define xrealloc realloc
+#define xfree free
+#if 0
+void *xmalloc(long);
+void *xcalloc(long, long);
+void *xrealloc(void *, long);
+void xfree(void *);
+#endif
+
+static void rehash(st_table *);
+
+#define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
+#define Calloc(n,s) (char*)xcalloc((n),(s))
+
+#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)(((void*)x),((void *)y)) == 0)
+
+#define do_hash(key,table) (unsigned int)(*(table)->type->hash)(((void*)key))
+#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
+
+/*
+ * MINSIZE is the minimum size of a dictionary.
+ */
+
+#define MINSIZE 8
+
+/*
+ Table of prime numbers 2^n+a, 2<=n<=30.
+*/
+static long primes[] = {
+ 8 + 3,
+ 16 + 3,
+ 32 + 5,
+ 64 + 3,
+ 128 + 3,
+ 256 + 27,
+ 512 + 9,
+ 1024 + 9,
+ 2048 + 5,
+ 4096 + 3,
+ 8192 + 27,
+ 16384 + 43,
+ 32768 + 3,
+ 65536 + 45,
+ 131072 + 29,
+ 262144 + 3,
+ 524288 + 21,
+ 1048576 + 7,
+ 2097152 + 17,
+ 4194304 + 15,
+ 8388608 + 9,
+ 16777216 + 43,
+ 33554432 + 35,
+ 67108864 + 15,
+ 134217728 + 29,
+ 268435456 + 3,
+ 536870912 + 11,
+ 1073741824 + 85,
+ 0
+};
+
+static int
+new_size(int size)
+{
+ int i;
+
+#if 0
+ for (i=3; i<31; i++) {
+ if ((1<<i) > size) return 1<<i;
+ }
+ return -1;
+#else
+ int newsize;
+
+ for (i = 0, newsize = MINSIZE;
+ i < sizeof(primes)/sizeof(primes[0]);
+ i++, newsize <<= 1)
+ {
+ if (newsize > size) return primes[i];
+ }
+ /* Ran out of polynomials */
+ return -1; /* should raise exception */
+#endif
+}
+
+#ifdef HASH_LOG
+static int collision = 0;
+static int init_st = 0;
+
+static void
+stat_col()
+{
+ FILE *f = fopen("/tmp/col", "w");
+ fprintf(f, "collision: %d\n", collision);
+ fclose(f);
+}
+#endif
+
+st_table*
+st_init_table_with_size(type, size)
+ struct st_hash_type *type;
+ int size;
+{
+ st_table *tbl;
+
+#ifdef HASH_LOG
+ if (init_st == 0)
+ {
+ init_st = 1;
+ atexit(stat_col);
+ }
+#endif
+
+ size = new_size(size); /* round up to prime number */
+
+ tbl = alloc(st_table);
+ tbl->type = type;
+ tbl->num_entries = 0;
+ tbl->num_bins = size;
+ tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+
+ return tbl;
+}
+
+st_table*
+st_init_table(type)
+ struct st_hash_type *type;
+{
+ return st_init_table_with_size(type, 0);
+}
+
+st_table*
+st_init_numtable(void)
+{
+ return st_init_table(&type_numhash);
+}
+
+st_table*
+st_init_numtable_with_size(size)
+ int size;
+{
+ return st_init_table_with_size(&type_numhash, size);
+}
+
+st_table*
+st_init_strtable(void)
+{
+ return st_init_table(&type_strhash);
+}
+
+st_table*
+st_init_strtable_with_size(size)
+ int size;
+{
+ return st_init_table_with_size(&type_strhash, size);
+}
+
+void
+st_free_table(table)
+ st_table *table;
+{
+ register st_table_entry *ptr, *next;
+ int i;
+
+ for(i = 0; i < table->num_bins; i++) {
+ ptr = table->bins[i];
+ while (ptr != 0) {
+ next = ptr->next;
+ free(ptr);
+ ptr = next;
+ }
+ }
+ free(table->bins);
+ free(table);
+}
+
+#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
+((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
+
+#ifdef HASH_LOG
+#define COLLISION collision++
+#else
+#define COLLISION
+#endif
+
+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
+ bin_pos = hash_val%(table)->num_bins;\
+ ptr = (table)->bins[bin_pos];\
+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) \
+ {\
+ COLLISION;\
+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
+ ptr = ptr->next;\
+ }\
+ ptr = ptr->next;\
+ }\
+} while (0)
+
+int
+st_lookup(table, key, value)
+ st_table *table;
+ register st_data_t key;
+ st_data_t *value;
+{
+ unsigned int hash_val, bin_pos;
+ register st_table_entry *ptr;
+
+ hash_val = do_hash(key, table);
+ FIND_ENTRY(table, ptr, hash_val, bin_pos);
+
+ if (ptr == 0)
+ {
+ return 0;
+ }
+ else {
+ if (value != 0) *value = ptr->record;
+ return 1;
+ }
+}
+
+#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
+do {\
+ st_table_entry *entry;\
+ if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) \
+ {\
+ rehash(table);\
+ bin_pos = hash_val % table->num_bins;\
+ }\
+ \
+ entry = alloc(st_table_entry);\
+ \
+ entry->hash = hash_val;\
+ entry->key = key;\
+ entry->record = value;\
+ entry->next = table->bins[bin_pos];\
+ table->bins[bin_pos] = entry;\
+ table->num_entries++;\
+} while (0);
+
+
+int
+st_insert(table, key, value)
+ register st_table *table;
+ register st_data_t key;
+ st_data_t value;
+{
+ unsigned int hash_val, bin_pos;
+ register st_table_entry *ptr;
+
+ hash_val = do_hash(key, table);
+ FIND_ENTRY(table, ptr, hash_val, bin_pos);
+
+ if (ptr == 0)
+ {
+ ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ return 0;
+ }
+ else {
+ ptr->record = value;
+ return 1;
+ }
+}
+
+void
+st_add_direct(table, key, value)
+ st_table *table;
+ st_data_t key;
+ st_data_t value;
+{
+ unsigned int hash_val, bin_pos;
+
+ hash_val = do_hash(key, table);
+ bin_pos = hash_val % table->num_bins;
+ ADD_DIRECT(table, key, value, hash_val, bin_pos);
+}
+
+static void
+rehash(table)
+ register st_table *table;
+{
+ register st_table_entry *ptr, *next, **new_bins;
+ int i, old_num_bins = table->num_bins, new_num_bins;
+ unsigned int hash_val;
+
+ new_num_bins = new_size(old_num_bins+1);
+ new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
+
+ for(i = 0; i < old_num_bins; i++) {
+ ptr = table->bins[i];
+ while (ptr != 0) {
+ next = ptr->next;
+ hash_val = ptr->hash % new_num_bins;
+ ptr->next = new_bins[hash_val];
+ new_bins[hash_val] = ptr;
+ ptr = next;
+ }
+ }
+ free(table->bins);
+ table->num_bins = new_num_bins;
+ table->bins = new_bins;
+}
+
+st_table*
+st_copy(old_table)
+ st_table *old_table;
+{
+ st_table *new_table;
+ st_table_entry *ptr, *entry;
+ int i, num_bins = old_table->num_bins;
+
+ new_table = alloc(st_table);
+ if (new_table == 0)
+ {
+ return 0;
+ }
+
+ *new_table = *old_table;
+ new_table->bins = (st_table_entry**)
+ Calloc((unsigned)num_bins, sizeof(st_table_entry*));
+
+ if (new_table->bins == 0)
+ {
+ free(new_table);
+ return 0;
+ }
+
+ for(i = 0; i < num_bins; i++) {
+ new_table->bins[i] = 0;
+ ptr = old_table->bins[i];
+ while (ptr != 0) {
+ entry = alloc(st_table_entry);
+ if (entry == 0)
+ {
+ free(new_table->bins);
+ free(new_table);
+ return 0;
+ }
+ *entry = *ptr;
+ entry->next = new_table->bins[i];
+ new_table->bins[i] = entry;
+ ptr = ptr->next;
+ }
+ }
+ return new_table;
+}
+
+int
+st_delete(table, key, value)
+ register st_table *table;
+ register st_data_t *key;
+ st_data_t *value;
+{
+ unsigned int hash_val;
+ st_table_entry *tmp;
+ register st_table_entry *ptr;
+
+ hash_val = do_hash_bin(*key, table);
+ ptr = table->bins[hash_val];
+
+ if (ptr == 0)
+ {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+
+ if (EQUAL(table, *key, ptr->key))
+ {
+ table->bins[hash_val] = ptr->next;
+ table->num_entries--;
+ if (value != 0) *value = ptr->record;
+ *key = ptr->key;
+ free(ptr);
+ return 1;
+ }
+
+ for(; ptr->next != 0; ptr = ptr->next) {
+ if (EQUAL(table, ptr->next->key, *key))
+ {
+ tmp = ptr->next;
+ ptr->next = ptr->next->next;
+ table->num_entries--;
+ if (value != 0) *value = tmp->record;
+ *key = tmp->key;
+ free(tmp);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+st_delete_safe(table, key, value, never)
+ register st_table *table;
+ register st_data_t *key;
+ st_data_t *value;
+ st_data_t never;
+{
+ unsigned int hash_val;
+ register st_table_entry *ptr;
+
+ hash_val = do_hash_bin(*key, table);
+ ptr = table->bins[hash_val];
+
+ if (ptr == 0)
+ {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+
+ for(; ptr != 0; ptr = ptr->next) {
+ if ((ptr->key != never) && EQUAL(table, ptr->key, *key))
+ {
+ table->num_entries--;
+ *key = ptr->key;
+ if (value != 0) *value = ptr->record;
+ ptr->key = ptr->record = never;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+delete_never( st_data_t key, st_data_t value, st_data_t never)
+{
+ if (value == never) return ST_DELETE;
+ return ST_CONTINUE;
+}
+
+void
+st_cleanup_safe(table, never)
+ st_table *table;
+ st_data_t never;
+{
+ int num_entries = table->num_entries;
+
+ st_foreach(table, delete_never, never);
+ table->num_entries = num_entries;
+}
+
+void
+st_foreach(table, func, arg)
+ st_table *table;
+ int (*func)(st_data_t key, st_data_t val, st_data_t arg);
+ st_data_t arg;
+{
+ st_table_entry *ptr, *last, *tmp;
+ enum st_retval retval;
+ int i;
+
+ for(i = 0; i < table->num_bins; i++) {
+ last = 0;
+ for(ptr = table->bins[i]; ptr != 0;) {
+ retval = (*func)(ptr->key, ptr->record, arg);
+ switch (retval) {
+ case ST_CONTINUE:
+ last = ptr;
+ ptr = ptr->next;
+ break;
+ case ST_STOP:
+ return;
+ case ST_DELETE:
+ tmp = ptr;
+ if (last == 0)
+ {
+ table->bins[i] = ptr->next;
+ }
+ else {
+ last->next = ptr->next;
+ }
+ ptr = ptr->next;
+ free(tmp);
+ table->num_entries--;
+ }
+ }
+ }
+}
+
+static int
+strhash(string)
+ register const char *string;
+{
+ register int c;
+
+#ifdef HASH_ELFHASH
+ register unsigned int h = 0, g;
+
+ while ((c = *string++) != '\0') {
+ h = ( h << 4 ) + c;
+ if ( g = h & 0xF0000000 )
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ return h;
+#elif HASH_PERL
+ register int val = 0;
+
+ while ((c = *string++) != '\0') {
+ val = val*33 + c;
+ }
+
+ return val + (val>>5);
+#else
+ register int val = 0;
+
+ while ((c = *string++) != '\0') {
+ val = val*997 + c;
+ }
+
+ return val + (val>>5);
+#endif
+}
+
+static int
+numcmp(x, y)
+ void *x, *y;
+{
+ return (st_ptr_t)x != (st_ptr_t)y;
+}
+
+static st_ptr_t
+numhash(n)
+ void *n;
+{
+ return (st_ptr_t)n;
+}
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
--- /dev/null
+!if $(FREEBUILD)
+TARGETNAME=osmtest
+!else
+TARGETNAME=osmtestd
+!endif
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+ osmt_slvl_vl_arb.c \
+ osmt_service.c \
+ osmt_multicast.c \
+ osmt_inform.c \
+ osmtest.c \
+ main.c \
+
+
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+ $(LIBPATH)\*\ibal.lib \
+ $(LIBPATH)\*\complib.lib \
+ $(TARGETPATH)\*\osmv_ibal.lib \
+ $(TARGETPATH)\*\opensm_ibal.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+ $(LIBPATH)\*\ibald.lib \
+ $(LIBPATH)\*\complibd.lib \
+ $(TARGETPATH)\*\osmv_ibald.lib \
+ $(TARGETPATH)\*\opensm_ibald.lib \
+ $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+ $(OSM_HOME)\include; \
+ $(OSM_HOME); \
+ $(WINIBHOME)\inc; \
+ $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of error code ranges for the various osmtest modules.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+/*
+ osmtest object
+ 0x0100 - 0x01FF
+
+ parser object
+ 0x0200 - 0x02FF
+
+ osmtest object
+ 0x0300 - 0x03FF
+
+*/
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Command line interface for osmtest.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN__
+#include <getopt.h>
+#endif
+#include <complib/cl_debug.h>
+#include "osmtest.h"
+
+/********************************************************************
+ D E F I N E G L O B A L V A R I A B L E S
+*********************************************************************/
+
+/*
+ This is the global osmtest object.
+ One osmtest object is required per subnet.
+ Future versions could support multiple subents by
+ instantiating more than one osmtest object.
+*/
+#define GUID_ARRAY_SIZE 64
+#define OSMT_DEFAULT_RETRY_COUNT 3
+#define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+#define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osmt_is_debug(void)
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage( )
+{
+ printf
+ ( "\n------- osmtest - Usage and options ----------------------\n" );
+ printf( "Usage: osmtest [options]\n" );
+ printf( "Options:\n" );
+ printf( "-f <c|a|v|s|e|f|m|q|t>\n"
+ "--flow <c|a|v|s|e|f|m|q|t>\n"
+ " This option directs osmtest to run a specific flow:\n"
+ " FLOW DESCRIPTION\n"
+ " c = create an inventory file with all nodes, ports and paths.\n"
+ " a = run all validation tests (expecting an input inventory)\n"
+ " v = only validate the given inventory file.\n"
+ " s = run service registration, un-registration and lease.\n"
+ " e = run event forwarding test.\n"
+ " f = flood the SA with queries accoring to the stress mode.\n"
+ " m = multicast flow.\n"
+ " q = QoS info - VLArb and SLtoVL tables.\n"
+ " t = run trap 64/65 flow. This flow requires running of external tool.\n"
+ " (default is all but QoS).\n\n" );
+ printf( "-w <trap_wait_time>\n"
+ "--wait <trap_wait_time>\n"
+ " This option specifies the wait time for trap 64/65 in seconds.\n"
+ " It is used only when running -f t - the trap 64/65 flow\n"
+ " (default to 10 sec).\n" );
+ printf( "-d <number>\n"
+ "--debug <number>\n"
+ " This option specifies a debug option.\n"
+ " These options are not normally needed.\n"
+ " The number following -d selects the debug\n"
+ " option to enable as follows:\n"
+ " OPT Description\n"
+ " --- -----------------\n"
+ " -d0 - Unused.\n"
+ " -d1 - Do not scan/compare path records.\n"
+ " -d2 - Force log flushing after each log message.\n"
+ " -d3 - Use mem tracking.\n"
+ " Without -d, no debug options are enabled.\n\n" );
+ printf( "-m <LID in hex>\n"
+ "--max_lid <LID in hex>\n"
+ " This option specifies the maximal LID number to be searched\n"
+ " for during inventory file build (default to 100).\n");
+ printf( "-g <GUID in hex>\n"
+ "--guid <GUID in hex>\n"
+ " This option specifies the local port GUID value\n"
+ " with which osmtest should bind. osmtest may be\n"
+ " bound to 1 port at a time.\n"
+ " Without -g, osmtest displays a menu of possible\n"
+ " port GUIDs and waits for user input.\n\n" );
+ printf( "-h\n"
+ "--help\n" " Display this usage info then exit.\n\n" );
+ printf( "-i <filename>\n"
+ "--inventory <filename>\n"
+ " This option specifies the name of the inventory file.\n"
+ " Normally, osmtest expects to find an inventory file,\n"
+ " which osmtest uses to validate real-time information\n"
+ " received from the SA during testing.\n"
+ " If -i is not specified, osmtest defaults to the file\n"
+ " 'osmtest.dat'.\n"
+ " See the -c option for related information.\n\n" );
+ printf( "-s\n"
+ "--stress\n"
+ " This option runs the specified stress test instead\n"
+ " of the normal test suite.\n"
+ " Stress test options are as follows:\n"
+ " OPT Description\n"
+ " --- -----------------\n"
+ " -s1 - Single-MAD response SA queries .\n"
+ " -s2 - Multi-MAD (RMPP) response SA queries.\n"
+ " -s3 - Multi-MAD (RMPP) Path Record SA queries.\n"
+ " Without -s, stress testing is not performed.\n\n" );
+ printf( "-M\n"
+ "--Multicast_Mode\n"
+ " This option specify length of Multicast test :\n"
+ " OPT Description\n"
+ " --- -----------------\n"
+ " -M1 - Short Multicast Flow (default) - single mode.\n"
+ " -M2 - Short Multicast Flow - multiple mode.\n"
+ " -M3 - Long MultiCast Flow - single mode.\n"
+ " -M4 - Long MultiCast Flow - mutiple mode.\n"
+ " Single mode - Osmtest is tested alone , with no other \n"
+ " apps that interact vs. OpenSM MC.\n"
+ " Multiple mode - Could be run with other apps using MC vs.\n"
+ " OpenSM."
+ " Without -M, default flow testing is performed.\n\n" );
+
+ printf( "-t <milliseconds>\n"
+ " This option specifies the time in milliseconds\n"
+ " used for transaction timeouts.\n"
+ " Specifying -t 0 disables timeouts.\n"
+ " Without -t, osmtest defaults to a timeout value of\n"
+ " 1 second.\n\n" );
+ printf( "-l\n"
+ "--log_file\n"
+ " This option defines the log to be the given file.\n"
+ " By default the log goes to stdout.\n\n");
+ printf( "-v\n"
+ " This option increases the log verbosity level.\n"
+ " The -v option may be specified multiple times\n"
+ " to further increase the verbosity level.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-V\n"
+ " This option sets the maximum verbosity level and\n"
+ " forces log flushing.\n"
+ " The -V is equivalent to '-vf 0xFF -d 2'.\n"
+ " See the -vf option for more information about.\n"
+ " log verbosity.\n\n" );
+ printf( "-vf <flags>\n"
+ " This option sets the log verbosity level.\n"
+ " A flags field must follow the -vf option.\n"
+ " A bit set/clear in the flags enables/disables a\n"
+ " specific log level as follows:\n"
+ " BIT LOG LEVEL ENABLED\n"
+ " ---- -----------------\n"
+ " 0x01 - ERROR (error messages)\n"
+ " 0x02 - INFO (basic messages, low volume)\n"
+ " 0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+ " 0x08 - DEBUG (diagnostic, high volume)\n"
+ " 0x10 - FUNCS (function entry/exit, very high volume)\n"
+ " 0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+ " 0x40 - currently unused.\n"
+ " 0x80 - currently unused.\n"
+ " Without -vf, osmtest defaults to ERROR + INFO (0x3).\n"
+ " Specifying -vf 0 disables all messages.\n"
+ " Specifying -vf 0xFF enables all messages (see -V).\n"
+ " High verbosity levels may require increasing\n"
+ " the transaction timeout with the -t option.\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu( )
+{
+ printf( "\n------- Interactive Menu -------\n" );
+ printf( "X - Exit.\n\n" );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+ char *argv[] )
+{
+ static osmtest_t osm_test;
+ osmtest_opt_t opt = { 0 };
+ ib_net64_t guid = 0;
+ int max_lid = 100;
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+ char flow_name[64];
+ boolean_t mem_track = FALSE;
+ uint32_t next_option;
+ const char *const short_option = "f:l:m:M:d:g:s:t:i:cvVh";
+
+ /*
+ * In the array below, the 2nd parameter specified the number
+ * of arguments as follows:
+ * 0: no arguments
+ * 1: argument
+ * 2: optional
+ */
+ const struct option long_option[] = {
+ {"create", 0, NULL, 'c'},
+ {"debug", 1, NULL, 'd'},
+ {"flow", 1, NULL, 'f'},
+ {"wait", 1, NULL, 'w'},
+ {"inventory", 1, NULL, 'i'},
+ {"max_lid", 1, NULL, 'm'},
+ {"guid", 1, NULL, 'g'},
+ {"help", 0, NULL, 'h'},
+ {"stress", 1, NULL, 's'},
+ {"MultiCast_Mode", 1, NULL, 'M'},
+ {"timeout", 1, NULL, 't'},
+ {"verbose", 0, NULL, 'v'},
+ {"log_file", 1, NULL, 'l'},
+ {"vf", 1, NULL, 'x'},
+ {"V", 0, NULL, 'V'},
+
+ {NULL, 0, NULL, 0} /* Required at end of array */
+ };
+
+ opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+ opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC;
+ opt.retry_count = OSMT_DEFAULT_RETRY_COUNT;
+ opt.force_log_flush = FALSE;
+ opt.stress = 0;
+ opt.log_file = NULL;
+ opt.create = FALSE;
+ opt.mmode = 1;
+ opt.ignore_path_records = FALSE; /* Do path Records too. */
+ opt.flow = 0; /* run all validation tests */
+ strcpy(flow_name, "All Validations");
+ strcpy( opt.file_name, "osmtest.dat" );
+
+ printf( "\nCommand Line Arguments\n" );
+ do
+ {
+ next_option = getopt_long_only( argc, argv, short_option,
+ long_option, NULL );
+
+ switch ( next_option )
+ {
+ case 'c':
+ /*
+ * Create the inventory file.
+ */
+ opt.create = TRUE;
+ printf( "\tCreating inventory file\n" );
+ break;
+
+ case 'i':
+ /*
+ * Specifies inventory file name.
+ */
+ if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX )
+ printf( "\nError: path name too long (ignored).\n" );
+ else
+ strcpy( opt.file_name, optarg );
+
+ printf( "\tFile = %s\n", opt.file_name );
+ break;
+
+ case 'f':
+ /*
+ * Specifies Flow .
+ */
+ if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX )
+ printf( "\nError: path name too long (ignored).\n" );
+ else
+ strcpy( flow_name, optarg );
+
+ if (!strcmp("c",optarg)) {
+ strcpy(flow_name, "Create Inventory");
+ opt.flow = 1;
+ } else if (!strcmp("v",optarg)) {
+ strcpy(flow_name, "Validate Inventory");
+ opt.flow = 2;
+ } else if (!strcmp("s",optarg)) {
+ strcpy(flow_name, "Services Registration");
+ opt.flow = 3;
+ } else if (!strcmp("e",optarg)) {
+ strcpy(flow_name, "Event Forwarding");
+ opt.flow = 4;
+ } else if (!strcmp("f",optarg)) {
+ strcpy(flow_name, "Stress SA");
+ opt.flow = 5;
+ } else if (!strcmp("m",optarg)) {
+ strcpy(flow_name, "Multicast");
+ opt.flow = 6;
+ } else if (!strcmp("q",optarg)) {
+ strcpy(flow_name, "QoS: VLArb and SLtoVL");
+ opt.flow = 7;
+ } else if (!strcmp("t", optarg)) {
+ strcpy(flow_name, "Trap 64/65");
+ opt.flow = 8;
+ } else if (!strcmp("a",optarg)) {
+ strcpy(flow_name, "All Validations");
+ opt.flow = 0;
+ } else {
+ printf( "\nError: un-known flow %s.\n",flow_name);
+ exit(2);
+ }
+ break;
+
+ case 'w':
+ /*
+ * Specifies trap 64/65 wait time
+ */
+ CL_ASSERT( strtol( optarg, NULL, 0 ) < 0x100 );
+ opt.wait_time = (uint8_t)strtol( optarg, NULL, 0 );
+ printf( "\tTrap 64/65 wait time = %d\n", opt.wait_time );
+ break;
+
+ case 'm':
+ /*
+ * Specifies the max LID to search for during exploration.
+ */
+ max_lid = atoi( optarg );
+ printf( "\tMAX-LID %u\n", max_lid );
+ break;
+
+ case 'g':
+ /*
+ * Specifies port guid with which to bind.
+ */
+ guid = cl_hton64( strtoull( optarg, NULL, 16 ));
+ printf( "\tGUID 0x%016" PRIx64 "\n", guid );
+ break;
+
+ case 't':
+ /*
+ * Specifies transaction timeout.
+ */
+ opt.transaction_timeout = strtol( optarg, NULL, 0 );
+ printf( "\tTransaction timeout = %d\n", opt.transaction_timeout );
+ break;
+
+ case 'l':
+ opt.log_file = optarg;
+ printf("\tLog File:%s\n", opt.log_file );
+ break;
+
+ case 'v':
+ /*
+ * Increases log verbosity.
+ */
+ log_flags = ( log_flags << 1 ) | 1;
+ printf( "\tVerbose option -v (log flags = 0x%X)\n", log_flags );
+ break;
+
+ case 'V':
+ /*
+ * Specifies maximum log verbosity.
+ */
+ log_flags = 0xFFFFFFFF;
+ opt.force_log_flush = TRUE;
+ printf( "\tEnabling maximum log verbosity\n" );
+ break;
+
+ case 's':
+ /*
+ * Perform stress test.
+ */
+ opt.stress = strtol( optarg, NULL, 0 );
+ printf( "\tStress test enabled: " );
+ switch ( opt.stress )
+ {
+ case 1:
+ printf( "Small SA queries\n" );
+ break;
+ case 2:
+ printf( "Large SA queries\n" );
+ break;
+ case 3:
+ printf( "Large Path Record SA queries\n" );
+ break;
+ default:
+ printf( "Unknown value %u (ignored)\n", opt.stress );
+ opt.stress = 0;
+ break;
+ }
+ break;
+
+ case 'M':
+ /*
+ * Perform stress test.
+ */
+ opt.mmode = strtol( optarg, NULL, 0 );
+ printf( "\tMultiCast test enabled: " );
+ switch ( opt.mmode )
+ {
+ case 1:
+ printf( "Short MC Flow - single mode (default)\n" );
+ break;
+ case 2:
+ printf( "Short MC Flow - multiple mode\n" );
+ break;
+ case 3:
+ printf( "Long MC Flow - single mode\n" );
+ break;
+ case 4:
+ printf( "Long MC Flow - multiple mode\n" );
+ break;
+ default:
+ printf( "Unknown value %u (ignored)\n", opt.stress );
+ opt.mmode = 0;
+ break;
+ }
+ break;
+
+ case 'd':
+ /*
+ * Debug Options
+ */
+ printf( "\tDebug Option: " );
+ switch ( strtol( optarg, NULL, 0 ) )
+ {
+ case 1:
+ printf( "Ignore Path Records.\n" );
+ opt.ignore_path_records = TRUE;
+ break;
+ case 2:
+ printf( "Force Log Flush.\n" );
+ opt.force_log_flush = TRUE;
+ break;
+ case 3:
+ printf( "Use Mem Tracking.\n" );
+ mem_track = TRUE;
+ break;
+ default:
+ printf( "Unknown value %ld (ignored)\n", strtol( optarg, NULL, 0 ) );
+ break;
+ }
+ break;
+
+ case 'h':
+ show_usage( );
+ return 0;
+
+ case 'x':
+ log_flags = strtol( optarg, NULL, 0 );
+ printf( "\t\t\t\tVerbose option -vf (log flags = 0x%X)\n",
+ log_flags );
+ break;
+
+ case -1:
+ printf( "Done with args\n" );
+ break;
+
+ default: /* something wrong */
+ abort( );
+ }
+
+ }
+ while( next_option != -1 );
+
+ printf( "\tFlow = %s\n", flow_name );
+
+ if (mem_track) __cl_mem_track(TRUE);
+
+
+ status = osmtest_init( &osm_test, &opt, ( osm_log_level_t ) log_flags );
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from osm_osmtest_init: %s.\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Guid may be zero going into this function if the user
+ * hasn't specified a binding port on the command line.
+ */
+ status = osmtest_bind( &osm_test, (uint16_t)max_lid, guid );
+ if (status != IB_SUCCESS) exit(status);
+
+ status = osmtest_run( &osm_test );
+ if (status != IB_SUCCESS) {
+ printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name);
+ } else {
+ printf("OSMTEST: TEST \"%s\" PASS\n", flow_name);
+ }
+ osmtest_destroy( &osm_test );
+
+ if (mem_track) cl_mem_display();
+
+#ifndef __WIN__
+ complib_exit();
+#endif
+
+ Exit:
+ return ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/*
+ * Abstract:
+ * Implementation of InformInfo testing flow..
+ * Top level is osmt_run_inform_info_flow:
+ * osmt_bind_inform_qp
+ * osmt_reg_unreg_inform_info
+ * osmt_send_trap_wait_for_forward
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+/* next error code: 16A */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+
+#include <opensm/osm_vendor_mlx_hca.h>
+#include "osmtest.h"
+#include "osmt_inform.h"
+
+/*
+ * Prepare an a synchronous QP (rcv) for sending inform info and
+ * handling the incoming reports.
+ *
+ */
+ib_api_status_t
+osmt_bind_inform_qp( IN osmtest_t * const p_osmt,
+ OUT osmt_qp_ctx_t *p_qp_ctx) {
+ ib_net64_t port_guid;
+ VAPI_hca_hndl_t hca_hndl;
+ VAPI_hca_id_t hca_id;
+ uint32_t port_num;
+ VAPI_ret_t vapi_ret;
+ IB_MGT_ret_t mgt_ret;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osmt_bind_inform_qp );
+
+ port_guid = p_osmt->local_port.port_guid;
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: "
+ "Binding to port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ) );
+
+ /* obtain the hca name and port num from the guid */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: "
+ "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n",
+ port_guid );
+
+ mgt_ret =
+ osm_vendor_get_guid_ca_and_port( p_osmt->p_vendor, port_guid,
+ &hca_hndl,&hca_id[0], &port_num );
+ if( mgt_ret != IB_MGT_OK )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_bind_inform_qp: ERR 0109: "
+ "Unable to obtain CA and port (%d).\n" );
+ goto Exit;
+ }
+
+#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000
+
+ strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id));
+ p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl;
+ p_qp_ctx->qp_bind_hndl.port_num = port_num;
+ p_qp_ctx->qp_bind_hndl.max_outs_sq = 10;
+ p_qp_ctx->qp_bind_hndl.max_outs_rq = 10;
+ p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY;
+
+ vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl);
+ if (vapi_ret != VAPI_OK)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_bind_inform_qp: ERR 0114: "
+ "Error initializing QP.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* we use the pre-allocated buffers for send and receive :
+ send from buf[0]
+ receive from buf[2]
+ */
+ p_qp_ctx->p_send_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN;
+ p_qp_ctx->p_recv_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN + MAD_BLOCK_SIZE);
+
+ /* Need to clear assigned memory of p_send_buf - before using it to send any data */
+ cl_memclr(p_qp_ctx->p_send_buf, MAD_BLOCK_SIZE);
+
+ status = IB_SUCCESS;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: "
+ "Initialized QP:0x%X in VAPI Mode\n",
+ p_qp_ctx->qp_bind_hndl.qp_id
+ );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: " "Binding to IB_MGT SMI\n" );
+
+ /* we also need a QP0 handle for sending packets */
+ mgt_ret = IB_MGT_get_handle( hca_id, port_num, IB_MGT_SMI,
+ &( p_qp_ctx->ib_mgt_qp0_handle ) );
+ if( IB_MGT_OK != mgt_ret )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_bind_inform_qp: ERR 0115: "
+ "Error obtaining IB_MGT handle to SMI.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return status;
+}
+
+/*
+ * Close the QP
+ */
+void
+osmt_unbind_inform_qp( IN osmtest_t * const p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx) {
+ osm_log_t *p_log = &p_osmt->log;
+
+ OSM_LOG_ENTER( p_log, osmt_unbind_inform_qp );
+
+ osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl);
+
+ IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_unbind_inform_qp: "
+ "Unbind QP handles.\n" );
+ OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/*
+ * Register/Unregister to receive the given InformInfo
+ *
+ * Uses the qp context to send the inform info mad.
+ * Wait for GetResp(InformInfoResp)
+ *
+ */
+ib_api_status_t
+osmt_reg_unreg_inform_info( IN osmtest_t *p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx,
+ IN ib_inform_info_t *p_inform_info,
+ IN uint8_t reg_flag
+ )
+{
+ ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_send_buf);
+ ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); /* SA Payload */
+ VAPI_ret_t vapi_ret;
+ VAPI_wc_desc_t wc_desc;
+ VAPI_ud_av_hndl_t avh;
+ static VAPI_wr_id_t wrid = 16198;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( &p_osmt->log, osmt_reg_unreg_inform_info );
+
+ /* init the MAD */
+ ib_mad_init_new( (ib_mad_t*)p_sa_mad,
+ IB_MCLASS_SUBN_ADM,
+ ( uint8_t ) 2,
+ IB_MAD_METHOD_SET,
+ cl_hton64( wrid ),
+ ( ib_net16_t ) 0,
+ 0 );
+ wrid++;
+ p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;
+
+ /* copy the reference inform info */
+ cl_memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));
+
+ if (reg_flag)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_reg_unreg_inform_info: "
+ "Subscribing InformInfo: Traps from lid:0x%X to 0x%X , trap num :0x%X.\n",
+ p_ii->lid_range_begin,p_ii->lid_range_end,p_ii->g_or_v.generic.trap_num);
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_reg_unreg_inform_info: "
+ "Un Subscribing InformInfo: Traps from lid:0x%X to 0x%X.\n",
+ p_ii->lid_range_begin, p_ii->lid_range_end);
+ }
+
+ /* set the subscribe bit */
+ if (reg_flag)
+ {
+ p_ii->subscribe = 1;
+ }
+ else
+ {
+ p_ii->subscribe = 0;
+ /*
+ * we need to set the QPN on the mad if we un-subsribe:
+ * o13-2.1.1 - QPN Field need to be set when un-subscribing.
+ */
+ ib_inform_info_set_qpn(p_ii,
+ cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.qp_num));
+ }
+
+ osm_dump_inform_info( &p_osmt->log,
+ p_ii,
+ OSM_LOG_DEBUG );
+
+ /* --------------------- PREP ------------------------- */
+ if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl,
+ p_qp_ctx->p_recv_buf,
+ 1, /* but we need only one mad at a time */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ wrid) != 1) {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0120: "
+ "Error posting recv bufs .\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_reg_unreg_inform_info: "
+ "Posted recv bufs .\n");
+
+ vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh);
+ if (vapi_ret != VAPI_OK)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0121: "
+ "Error Preparing AVH (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_reg_unreg_inform_info: "
+ "Prepared AVH .\n");
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_sa_mad( p_log, (ib_sa_mad_t *)(p_qp_ctx->p_send_buf), OSM_LOG_DEBUG);
+ /* for (i = 56; i < 253; i++) { */
+ /* if ( i % 8 == 0 ) { printf("\n %d : ", i);} */
+ /* printf("0x%02X ", p_qp_ctx->p_send_buf[i]); */
+ /* } */
+ printf("\n");
+ }
+
+ /* --------------------- SEND ------------------------- */
+ vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl,
+ wrid,
+ p_qp_ctx->p_send_buf,
+ 1, /* SA is QP1 */
+ 0, /* SL is 0 */
+ OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
+ avh
+ );
+ if (vapi_ret != VAPI_OK)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0122: "
+ "Error sending mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+ p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
+ &wc_desc,
+ 20,
+ 10000,
+ NULL);
+ if (vapi_ret != VAPI_OK)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0123: "
+ "Error getting send completion (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if (wc_desc.status != VAPI_SUCCESS)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0124: "
+ "Error on send completion (%s) (%d).\n",
+ VAPI_strerror_sym(wc_desc.status), wc_desc.status );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_reg_unreg_inform_info: "
+ "Sent MAD .\n");
+
+ /* --------------------- RECV ------------------------- */
+ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+ p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+ &wc_desc,
+ 20,
+ 10000,
+ &avh);
+ if (vapi_ret != VAPI_SUCCESS)
+ {
+ if (vapi_ret == VAPI_CQ_EMPTY)
+ {
+ status = IB_TIMEOUT;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0125: "
+ "Error receiving mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ }
+ goto Exit;
+ }
+
+ /* check to see if successful - by exmaine of the subscribe bit */
+ p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+ if (p_sa_mad->status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( (ib_mad_t *)p_sa_mad ));
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: "
+ "Expected a IB_MAD_METHOD_GET_RESP but got:(%X).\n",
+ p_sa_mad->method);
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: "
+ "Expected a IB_MAD_ATTR_INFORM_INFO but got:(%X).\n",
+ cl_ntoh16(p_sa_mad->attr_id));
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
+ if (!p_ii->subscribe)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_reg_unreg_inform_info: ERR 0126: "
+ "Subscribe/Unsubscribe Failed.\n");
+ status = IB_REMOTE_ERROR;
+ }
+
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+/*
+ * Send a trap (Subn LID Route) Trap(Notice) through the regular
+ * connection QP connection (targetted at QP0)
+ *
+ * Wait for the trap repress
+ */
+ib_api_status_t
+osmt_send_trap_wait_for_forward( IN osmtest_t * const p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx
+ )
+{
+ ib_smp_t *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf);
+ ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
+ ib_sa_mad_t * p_sa_mad;
+ IB_MGT_ret_t mgt_res;
+ VAPI_ret_t vapi_ret;
+ VAPI_wc_desc_t wc_desc;
+ VAPI_ud_av_hndl_t avh;
+ IB_ud_av_t av;
+ static VAPI_wr_id_t wrid = 2222;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_send_trap_wait_for_forward );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_send_trap_wait_for_forward: "
+ "Sending Traps to QP0 of SA LID:%X\n",
+ p_osmt->local_port.sm_lid);
+
+ /* init the MAD */
+ cl_memclr(p_smp, sizeof(ib_smp_t));
+ ib_mad_init_new( (ib_mad_t*)p_smp,
+ IB_MCLASS_SUBN_LID,
+ ( uint8_t ) 2,
+ IB_MAD_METHOD_TRAP,
+ cl_hton64( wrid),
+ ( ib_net16_t ) 0,
+ 0 );
+
+ wrid++;
+ p_smp->attr_id = IB_MAD_ATTR_NOTICE;
+
+ /* prepare the notice */
+ p_ntc->generic_type = 0x82;/* generic, type = 2 */
+ ib_notice_set_prod_type(p_ntc, 1);
+ p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
+ p_ntc->issuer_lid = cl_hton16(2);
+
+ /* --------------------- PREP ------------------------- */
+ if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl,
+ p_qp_ctx->p_recv_buf,
+ 1, /* we need to receive both trap repress and report */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ wrid) != 1) {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 0127: "
+ "Error posting recv bufs .\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "Posted recv bufs .\n");
+
+ av.dlid = p_osmt->local_port.sm_lid;
+ av.grh_flag = FALSE;
+
+ /* EZ: returned in HACK: use constants */
+ av.static_rate = 0; /* p_mad_addr->static_rate; */
+ av.src_path_bits = 1 ; /* p_mad_addr->path_bits; */
+ av.sl = 0 ; /* p_mad_addr->addr_type.gsi.service_level; */
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "av.dlid 0x%X, "
+ "av.static_rate %d, "
+ "av.path_bits %d.\n",
+ cl_ntoh16( av.dlid ), av.static_rate, av.src_path_bits );
+ }
+
+ /* send it */
+ mgt_res = IB_MGT_send_mad( p_qp_ctx->ib_mgt_qp0_handle, p_smp, /* actual payload */
+ &av, /* address vector */
+ wrid, /* casting the mad wrapper pointer for err cb */
+ p_osmt->opt.transaction_timeout );
+ if( mgt_res != IB_MGT_OK )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 0128: "
+ "Error sending mad (%d).\n", mgt_res );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh);
+ if (vapi_ret != VAPI_OK)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 0129: "
+ "Error Preparing AVH (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "Prepared AVH .\n");
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "Trap MAD Sent.\n");
+
+ /* --------------------- RECV ------------------------- */
+ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+ p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+ &wc_desc,
+ 200,
+ 10000,
+ &avh);
+ if (vapi_ret != VAPI_SUCCESS)
+ {
+ if (vapi_ret == VAPI_CQ_EMPTY)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 0130: "
+ "Timeout receiving mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_TIMEOUT;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 0131: "
+ "Error receiving mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ }
+ goto Exit;
+ }
+
+ /* check to see if successful - by exmaine of the subscribe bit */
+ p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+ if (p_sa_mad->method == IB_MAD_METHOD_REPORT)
+ {
+ if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_send_trap_wait_for_forward: "
+ "Received the Report !\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 1020"
+ "Did not receive a Report(Notice) but attr:%d.\n",
+ cl_ntoh16(p_sa_mad->attr_id)
+ );
+ }
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: ERR 1020"
+ "Receive an Un-Expected Method:%d.\n",
+ p_smp->method
+ );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
+
+
+
+
+/*
+ * Wait for a trap on QPn
+ *
+ */
+ib_api_status_t
+osmt_trap_wait( IN osmtest_t * const p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx
+ )
+{
+ ib_smp_t *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf);
+ ib_sa_mad_t * p_sa_mad;
+ VAPI_ret_t vapi_ret;
+ VAPI_wc_desc_t wc_desc;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_trap_wait );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_trap_wait: "
+ "Waiting for Traps under QP:0x%X of SA LID:0x%X\n",
+ cl_ntoh16(p_osmt->local_port.sm_lid));
+
+ /* --------------------- RECV ------------------------- */
+ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+ p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+ &wc_desc,
+ // 200,
+ p_osmt->opt.wait_time * 100,
+ 10000,
+ NULL);
+ if (vapi_ret != VAPI_SUCCESS)
+ {
+ if (vapi_ret == VAPI_CQ_EMPTY)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_trap_wait: ERR 0130: "
+ "Timeout receiving mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_TIMEOUT;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_trap_wait: ERR 0131: "
+ "Error receiving mad (%s).\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ }
+ goto Exit;
+ }
+
+ /* check to see if successful - by exmaine of the subscribe bit */
+ p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+ if (p_sa_mad->method == IB_MAD_METHOD_REPORT)
+ {
+ if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_trap_wait: "
+ "Received the Report !\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_trap_wait: ERR 1020"
+ "Did not receive a Report(Notice) but attr:%d.\n",
+ cl_ntoh16(p_sa_mad->attr_id)
+ );
+ }
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_trap_wait: ERR 1020"
+ "Receive an Un-Expected Method:%d.\n",
+ p_smp->method
+ );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+/*
+ * Initialize an inform info attribute:
+ * Catch all traps in the lid range of the p_osmt
+ *
+ */
+ib_api_status_t
+osmt_init_inform_info(IN osmtest_t * const p_osmt,
+ OUT ib_inform_info_t* p_ii) {
+
+ cl_memclr(p_ii, sizeof(ib_inform_info_t));
+ /* p_ii->lid_range_begin = cl_hton16(1); */
+ p_ii->lid_range_begin = 0xFFFF;
+ p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+ p_ii->is_generic = 1; /* have to choose */
+ p_ii->trap_type = 0xFFFF; /* ALL */
+ p_ii->g_or_v.generic.trap_num = 0xFFFF; /* ALL */
+ p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */
+ p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */
+ return IB_SUCCESS;
+}
+
+ib_api_status_t
+osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt,
+ IN ib_net16_t trap_num,
+ OUT ib_inform_info_t* p_ii) {
+
+ cl_memclr(p_ii, sizeof(ib_inform_info_t));
+ /* p_ii->lid_range_begin = cl_hton16(1); */
+ p_ii->lid_range_begin = 0xFFFF;
+ p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+ p_ii->is_generic = 1; /* have to choose */
+ p_ii->trap_type = 0xFFFF; /* ALL */
+ p_ii->g_or_v.generic.trap_num = trap_num; /* ALL */
+ p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */
+ p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */
+ return IB_SUCCESS;
+}
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that match the sent one
+ *
+ */
+ib_api_status_t
+osmt_run_inform_info_flow( IN osmtest_t * const p_osmt ) {
+ ib_inform_info_t inform_info;
+ ib_api_status_t status;
+ osmt_qp_ctx_t qp_ctx;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_run_inform_info_flow);
+
+ /* bind the QP */
+ status = osmt_bind_inform_qp( p_osmt, &qp_ctx);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* init the inform info */
+ osmt_init_inform_info(p_osmt, &inform_info);
+
+ /* first try to un-subscribe */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 0);
+ /* WAS IB_REMOTE_ERROR */
+ if (status != IB_REMOTE_ERROR)
+ {
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "Error during UnSubscribe: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "Expected Failure to UnSubscribe non existing InformInfo\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+
+ /* send the inform info registration */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* send a trap through QP0 and wait on QPN */
+ status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "Error during Send Trap and Wait For Report: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+
+ /* try to un-subscribe for cleanup */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 0);
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "Error during UnSubscribe: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+ else
+ {
+ if (status == IB_REMOTE_ERROR)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "Remote Error during UnSubscribe.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+
+
+ Exit:
+ osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that match the sent one
+ *
+ */
+ib_api_status_t
+osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt) {
+ ib_inform_info_t inform_info;
+ ib_api_status_t status;
+ osmt_qp_ctx_t qp_ctx;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_run_trap64_65_flow);
+
+ /* bind the QP */
+ status = osmt_bind_inform_qp( p_osmt, &qp_ctx);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* init the inform info */
+ osmt_init_inform_info_by_trap(p_osmt,
+ cl_hton16(64),
+ &inform_info);
+
+
+
+
+ /* send the inform info registration */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /*--------------------- PREP -------------------------*/
+ if (osmt_mtl_mad_post_recv_bufs(
+ &qp_ctx.qp_bind_hndl,
+ qp_ctx.p_recv_buf,
+ 1, /* we need to reveive the report */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ 1) != 1) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_trap64_65_flow: ERR 0127: "
+ "Error posting recv bufs for trap 64.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_run_trap64_65_flow: "
+ "Posted recv bufs for trap 64.\n");
+
+ /* init the inform info */
+ osmt_init_inform_info_by_trap(p_osmt,
+ cl_hton16(65),
+ &inform_info);
+
+
+ /* send the inform info registration */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /*--------------------- PREP -------------------------*/
+ if (osmt_mtl_mad_post_recv_bufs(
+ &qp_ctx.qp_bind_hndl,
+ qp_ctx.p_recv_buf,
+ 1, /* we need to reveive the report */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ 1) != 1) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_trap64_65_flow: ERR 0127: "
+ "Error posting recv bufs for trap 65.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_run_trap64_65_flow: "
+ "Posted recv bufs for trap 65.\n");
+ /* Sleep for x seconds in order to allow external script trap generation */
+ /* sleep (p_osmt->opt.wait_time); */
+
+ /* wait for a trap on QPN */
+ status = osmt_trap_wait(p_osmt, &qp_ctx);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_trap64_65_flow:"
+ "Error during Send Trap and Wait For Report: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+
+
+ /* try to un-subscribe for cleanup */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 0);
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_trap64_65_flow:"
+ "Error during UnSubscribe: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+
+
+ Exit:
+ osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
+
+#endif /* OSM_VENDOR_INTF_MTL */
+
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#ifndef __OSMT_INFORM__
+#define __OSMT_INFORM__
+
+#include <opensm/osm_vendor_mlx_inout.h>
+#include <ib_mgt.h>
+#include "osmt_mtl_regular_qp.h"
+
+typedef struct _osmt_qp_ctx
+{
+ osmt_mtl_mad_res_t qp_bind_hndl;
+ uint8_t *p_send_buf;
+ uint8_t *p_recv_buf;
+ IB_MGT_mad_hndl_t ib_mgt_qp0_handle;
+}
+osmt_qp_ctx_t;
+
+ib_api_status_t
+osmt_bind_inform_qp( IN osmtest_t * const p_osmt,
+ OUT osmt_qp_ctx_t *p_qp_ctx);
+
+void
+osmt_unbind_inform_qp( IN osmtest_t * const p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx);
+
+
+ib_api_status_t
+osmt_reg_unreg_inform_info( IN osmtest_t *p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx,
+ IN ib_inform_info_t *p_inform_info,
+ IN uint8_t reg_flag
+ );
+
+ib_api_status_t
+osmt_trap_wait( IN osmtest_t * const p_osmt,
+ IN osmt_qp_ctx_t *p_qp_ctx
+ );
+
+ib_api_status_t
+osmt_init_inform_info(IN osmtest_t * const p_osmt,
+ OUT ib_inform_info_t* p_ii);
+
+ib_api_status_t
+osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt,
+ IN ib_net16_t trap_num,
+ OUT ib_inform_info_t* p_ii);
+
+#endif // __OSMT_INFORM__
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/* - Mellanox Confidential and Proprietary -
+ *
+ * Copyright (C) Jul. 2001, Mellanox Technologies Ltd. ALL RIGHTS RESERVED.
+ *
+ * Except as specifically permitted herein, no portion of the information,
+ * including but not limited to object code and source code, may be reproduced,
+ * modified, distributed, republished or otherwise exploited in any form or by
+ * any means for any purpose without the prior written permission of Mellanox
+ * Technologies Ltd. Use of software subject to the terms and conditions
+ * detailed in the file "LICENSE.txt".
+ *
+ * End of legal section ......................................................
+ *
+ * osmt_mtl_regular_qp.c -
+ * Provide Simple Interface for Sending and Receiving MADS through a regular QP
+ *
+ * Creation date:
+ *
+ * Version: $Id: osmt_mtl_regular_qp.c,v 1.1 2003/03/20 16:41:48 eitan Exp $
+ *
+ * Authors:
+ * Eitan Zahavi
+ *
+ * Changes:
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <mtl_common.h>
+#include <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+#include <osmt_mtl_regular_qp.h>
+#include <complib/cl_types.h>
+/*
+ * Initialize the QP etc.
+ * Given in res: port_num, max_outs_sq, max_outs_rq
+ */
+VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t *res)
+{
+ VAPI_ret_t ret;
+ VAPI_hca_port_t hca_port_info;
+ VAPI_qp_init_attr_t qp_init_attr;
+ VAPI_qp_prop_t qp_prop;
+ VAPI_cqe_num_t act_num;
+
+ /* Get HCA LID */
+ ret = VAPI_query_hca_port_prop(res->hca_hndl, res->port_num , &hca_port_info); VAPI_CHECK_RET;
+ res->slid = hca_port_info.lid;
+
+ /* Get a PD */
+ ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl)); VAPI_CHECK_RET;
+
+ /* Create CQ for RQ and SQ*/ /* TBD - Check we have enough act nums */
+ ret = VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1, &(res->sq_cq_hndl), &act_num);
+ VAPI_CHECK_RET;
+ ret = VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1, &(res->rq_cq_hndl), &act_num);
+ VAPI_CHECK_RET;
+
+
+ /* register event handlers for polling(block mode) internal use*/
+ /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */
+ /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */
+ /* VAPI_CHECK_RET; */
+ /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */
+ /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */
+ /* VAPI_CHECK_RET; */
+
+ /* Create QP */
+ qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1;
+ qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1;
+ qp_init_attr.cap.max_sg_size_sq = 4;
+ qp_init_attr.cap.max_sg_size_rq = 4;
+
+ qp_init_attr.pd_hndl = res->pd_hndl;
+ qp_init_attr.rdd_hndl = 0;
+ qp_init_attr.rq_cq_hndl = res->rq_cq_hndl;
+ qp_init_attr.rq_sig_type = VAPI_SIGNAL_ALL_WR; /* That's default for IB */
+ qp_init_attr.sq_cq_hndl = res->sq_cq_hndl;
+ qp_init_attr.sq_sig_type = VAPI_SIGNAL_REQ_WR;
+ qp_init_attr.ts_type = VAPI_TS_UD;
+
+ ret= VAPI_create_qp(res->hca_hndl,&qp_init_attr,&(res->qp_hndl),&qp_prop);
+ VAPI_CHECK_RET;
+ res->qp_id.qp_num= qp_prop.qp_num;
+
+ return(VAPI_OK);
+}
+
+VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t *res)
+{
+ VAPI_ret_t ret;
+
+ VAPI_qp_attr_t qp_attr;
+ VAPI_qp_attr_mask_t qp_attr_mask;
+ VAPI_qp_cap_t qp_cap;
+
+
+ /*
+ * Change QP to INIT
+ *
+ */
+ QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+ qp_attr.qp_state = VAPI_INIT;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+ qp_attr.pkey_ix = 0;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PKEY_IX);
+ qp_attr.port = res->port_num;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PORT);
+ qp_attr.qkey = res->qkey;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QKEY);
+
+ /* If I do not set this mask, I get an error from HH. QPM should catch it */
+ ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET;
+
+ return(ret);
+
+}
+
+VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t *res)
+{
+ VAPI_ret_t ret;
+
+ VAPI_qp_attr_t qp_attr;
+ VAPI_qp_attr_mask_t qp_attr_mask;
+ VAPI_qp_cap_t qp_cap;
+
+ /*
+ * Change QP to RTR
+ *
+ */
+ QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+ qp_attr.qp_state = VAPI_RTR;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+ /* qp_attr.rq_psn = 0; */
+ /* QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */
+
+ ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET;
+
+ /*
+ * Change QP to RTS
+ *
+ */
+ QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+ qp_attr.qp_state = VAPI_RTS;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+ qp_attr.sq_psn = 0;
+ QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_SQ_PSN);
+
+ ret = VAPI_modify_qp(res->hca_hndl,res->qp_hndl,&qp_attr,&qp_attr_mask,&qp_cap); VAPI_CHECK_RET;
+
+ return(ret);
+}
+
+VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t *res)
+{
+
+ VAPI_ret_t ret;
+
+ VAPI_mrw_t mr_in, mr_out;
+
+
+ res->buf_size = (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1);
+
+ /* Register single memory address region for all buffers */
+ res->buf_ptr = VMALLOC(res->buf_size);
+
+ if (res->buf_ptr == ((VAPI_virt_addr_t)NULL)) {
+ ret = VAPI_EAGAIN;
+ VAPI_CHECK_RET;
+ }
+
+ /* Enable local and remote access to memory region */
+ mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE;
+ mr_in.l_key =0;
+ mr_in.pd_hndl = res->pd_hndl;
+ mr_in.r_key =0;
+ mr_in.size = res->buf_size;
+ ASSERT_VOIDP2UINTN(res->buf_ptr);
+ mr_in.start = (VAPI_virt_addr_t)(uintn_t)(res->buf_ptr);
+ mr_in.type = VAPI_MR;
+
+ ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out); VAPI_CHECK_RET;
+
+ res->l_key = mr_out.l_key;
+
+ return(ret);
+}
+
+VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t* res)
+{
+ VAPI_ret_t ret;
+
+ res->pd_hndl= VAPI_INVAL_HNDL;
+ res->rq_cq_hndl= VAPI_INVAL_HNDL;
+ res->sq_cq_hndl= VAPI_INVAL_HNDL;
+ res->sq_cq_eventh= VAPI_INVAL_HNDL;
+ res->rq_cq_eventh= VAPI_INVAL_HNDL;
+ res->qp_hndl= VAPI_INVAL_HNDL;
+ res->mr_hndl= VAPI_INVAL_HNDL;
+
+ /*
+ * Create QP
+ *
+ */
+ ret = osmt_mtl_get_qp_resources(res);
+ if (ret != VAPI_OK) {
+ return ret;
+ }
+
+ /*
+ * Move to init
+ *
+ */
+ ret = osmt_mtl_qp_init(res);
+ if (ret != VAPI_OK) {
+ return ret;
+ }
+
+
+ /*
+ * Initialize memory regions
+ *
+ */
+ ret = osmt_mtl_mad_create_mr(res);
+ if (ret != VAPI_OK) {
+ return ret;
+ }
+
+ /* only now move to RTR and RTS */
+ ret = osmt_mtl_qp_2_rtr_rts(res);
+ if (ret != VAPI_OK) {
+ return ret;
+ }
+
+ return VAPI_OK;
+}
+
+
+
+VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t *res)
+{
+ if (res->qp_hndl != VAPI_INVAL_HNDL) {
+ VAPI_destroy_qp(res->hca_hndl,res->qp_hndl);
+ }
+ if (res->sq_cq_eventh != VAPI_INVAL_HNDL) {
+ EVAPI_clear_comp_eventh(res->hca_hndl,res->sq_cq_eventh);
+ }
+ if (res->rq_cq_eventh != VAPI_INVAL_HNDL) {
+ EVAPI_clear_comp_eventh(res->hca_hndl,res->rq_cq_eventh);
+ }
+ if (res->rq_cq_hndl != VAPI_INVAL_HNDL) {
+ VAPI_destroy_cq(res->hca_hndl,res->rq_cq_hndl);
+ }
+ if (res->sq_cq_hndl != VAPI_INVAL_HNDL) {
+ VAPI_destroy_cq(res->hca_hndl,res->sq_cq_hndl);
+ }
+ if (res->mr_hndl != VAPI_INVAL_HNDL) {
+ VAPI_deregister_mr(res->hca_hndl,res->mr_hndl);
+ }
+ if (res->pd_hndl != VAPI_INVAL_HNDL) {
+ VAPI_dealloc_pd(res->hca_hndl,res->pd_hndl);
+ }
+#if 0
+ /* open/close of HCA should be done system wide - not per application */
+ if (res->hca_hndl != VAPI_INVAL_HNDL) {
+ VAPI_close_hca(res->hca_hndl); /* TBD: HCA_open/close should be done on a system wide basis */
+ }
+#endif
+ return VAPI_OK;
+}
+VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t* res, int16_t dlid, VAPI_ud_av_hndl_t *avh_p)
+{
+ VAPI_ud_av_t av;
+ VAPI_ret_t ret;
+
+ av.dlid= dlid;
+ av.port= res->port_num;
+ av.sl = 0; /* dest->sl; */
+ av.src_path_bits= 0; /* dest->ee_dlid.dst_path_bits; */
+ av.static_rate = 0;
+ /* GRH ? */
+ av.grh_flag= 0;
+
+ ret= VAPI_create_addr_hndl(res->hca_hndl,res->pd_hndl, &av,avh_p);
+ if (ret != VAPI_OK) {
+ MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__,
+ VAPI_strerror_sym(ret));
+ return ret;
+ }
+ return VAPI_OK;
+}
+
+VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t* res, VAPI_wr_id_t id, void* mad,
+ VAPI_qp_num_t dest_qp, IB_sl_t sl,u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh)
+{
+ VAPI_sr_desc_t sr;
+ VAPI_sg_lst_entry_t sg_entry;
+ VAPI_ret_t ret;
+
+ /* building SEND request */
+ sr.opcode= VAPI_SEND;
+ sr.remote_ah= avh;
+ sr.remote_qp= dest_qp;
+ sr.remote_qkey= dest_qkey;
+
+ sr.id = id;
+ sr.set_se= FALSE;
+ sr.fence= FALSE;
+ sr.comp_type= VAPI_SIGNALED;
+ sr.sg_lst_len= 1;
+ sr.sg_lst_p= &sg_entry;
+ ASSERT_VOIDP2UINTN(mad);
+ sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)(mad);
+ sg_entry.len= MAD_SIZE;
+ sg_entry.lkey= res->l_key;
+
+ ret= VAPI_post_sr(res->hca_hndl,res->qp_hndl,&sr);
+ if (ret != VAPI_OK) {
+ MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n",
+ VAPI_strerror_sym(ret));
+ return ret;
+ }
+
+ return VAPI_OK;
+}
+
+int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t* res, void *buf_array,
+ u_int32_t num_o_bufs,u_int32_t size, VAPI_wr_id_t start_id)
+{
+ uint32_t i;
+ void* cur_buf;
+ VAPI_rr_desc_t rr;
+ VAPI_sg_lst_entry_t sg_entry;
+ VAPI_ret_t ret;
+
+ rr.opcode= VAPI_RECEIVE;
+ rr.comp_type= VAPI_SIGNALED; /* All with CQE (IB compliant) */
+ rr.sg_lst_len= 1; /* single buffers */
+ rr.sg_lst_p= &sg_entry;
+ sg_entry.lkey= res->l_key;
+ cur_buf = buf_array;
+ for (i= 0; i < num_o_bufs ; i++ ) {
+ rr.id= start_id+i; /* WQE id used is the index to buffers ptr array */
+ ASSERT_VOIDP2UINTN(cur_buf);
+ sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)cur_buf;
+ sg_entry.len= size;
+ memset(cur_buf,0x00,size); /* fill with 0 */
+ ret= VAPI_post_rr(res->hca_hndl,res->qp_hndl,&rr);
+ if (ret != VAPI_OK) {
+ MTL_ERROR1(__FUNCTION__ ": failed posting RQ WQE (%s)\n",VAPI_strerror_sym(ret));
+ return i;
+ }
+ MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n",cur_buf);
+ cur_buf += size;
+ }
+
+ return i; /* num of buffers posted */
+}
+
+
+#ifndef __KERNEL__
+VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca,VAPI_cq_hndl_t cq,
+ VAPI_wc_desc_t *wc_desc_p,
+ u_int32_t max_poll, u_int32_t poll_sleep,
+ VAPI_ud_av_hndl_t *avh_p)
+{
+ VAPI_ret_t ret = VAPI_CQ_EMPTY;
+ u_int32_t poll_cnt= 0;
+
+
+ /* wait for something to arrive */
+ while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) {
+ ret= VAPI_poll_cq(hca,cq,wc_desc_p);
+ /* don't sleep if we already succeeded) */
+ if (ret != VAPI_CQ_EMPTY) {
+ break;
+ }
+ usleep(poll_sleep);
+ poll_cnt++;
+ }
+
+ /* if passed an AVH to destory - do it */
+ if (avh_p != NULL) {
+ VAPI_destroy_addr_hndl(hca,*avh_p);
+ }
+
+ if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) {
+ MTL_DEBUG1(__FUNCTION__ ": Failed to get completion on wq after %d polls.\n",max_poll);
+ return VAPI_CQ_EMPTY;
+ }
+
+ if (ret != VAPI_OK) {
+ MTL_DEBUG1(__FUNCTION__ ": VAPI_poll_cq failed with ret=%s on sq_cq\n",mtl_strerror_sym(ret));
+ return ret;
+ }
+
+ if (wc_desc_p->status != VAPI_SUCCESS) {
+ MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n",wc_desc_p->status);
+ }
+
+ return VAPI_OK;
+}
+#endif
+
+
+
+#ifdef __KERNEL__
+int init_module(void)
+{
+ MTL_TRACE1("mad module loaded.\n");
+ return(0);
+}
+
+void cleanup_module(void)
+{
+ MTL_TRACE1("mad module unloaded.\n");
+}
+#endif
+
+#endif /* OSM_VENDOR_INTF_MTL */
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/* - Mellanox Confidential and Proprietary -
+ *
+ * Copyright (C) Apr. 2001, Mellanox Technologies Ltd. ALL RIGHTS RESERVED.
+ *
+ * Except as specifically permitted herein, no portion of the information,
+ * including but not limited to object code and source code, may be reproduced,
+ * modified, distributed, republished or otherwise exploited in any form or by
+ * any means for any purpose without the prior written permission of Mellanox
+ * Technologies Ltd. Use of software subject to the terms and conditions
+ * detailed in the file "LICENSE.txt".
+ *
+ * End of legal section ......................................................
+ *
+ * mad.h -
+ * Header file for common special QP resources creation code.
+ *
+ * Creation date:
+ *
+ * Version: $Id: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan Exp $
+ *
+ * Authors:
+ * Elazar Raab
+ *
+ * Changes:
+ */
+
+#ifndef H_MAD_H
+#define H_MAD_H
+
+#include <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+
+
+#if defined(MAD_IN) || defined(MAD_OUT)
+#error MACROS MAD_IN and MAD_OUT are in use, do not override
+#endif
+#define MAD_IN
+#define MAD_OUT
+
+
+
+/* HCA Constants */
+#define HCA_ID "mt21108_pci0"
+#define GRH_LEN 40
+#define KNOWN_QP1_QKEY 0x80010000
+
+
+#define MAX_OUTS_SQ 2 /* Max. buffers posted for requests in SQ */
+#define MAX_OUTS_RQ 5 /* Max. buffers posted for responses in RQ */
+
+#define MAX_POLL_CNT 300
+#define POLL_SLEEP 1 /* for usleep */
+
+#define MAD_SIZE 256 /* MADs are always 256B */
+#define MAD_ATTR_OFFSET 16
+#define MAD_TID_OFFSET 8
+
+
+
+
+/* Verbs SQP resources handles */
+typedef struct {
+ VAPI_hca_id_t hca_id; /*id of HCA*/
+ u_int8_t port_num; /* the port num to use */
+ VAPI_hca_hndl_t hca_hndl; /*handle of HCA*/
+ VAPI_qp_hndl_t qp_hndl; /*handle of QP I use*/
+ VAPI_mr_hndl_t mr_hndl; /*handle of memory region*/
+ VAPI_cq_hndl_t rq_cq_hndl, sq_cq_hndl; /*handle of send & receive completion Queues*/
+ VAPI_pd_hndl_t pd_hndl; /*handle of Partition Domain*/
+ /* VAPI_ud_av_hndl_t av_hndl;*/
+ IB_lid_t slid; /*LID*/
+ void *buf_ptr; /*mem buffer for outstanding pkts*/
+ MT_size_t buf_size; /*size of mem buffer for outstanding pkts*/
+
+ u_int32_t max_outs_sq; /*max # of outstanding pkts in send queue*/
+ u_int32_t max_outs_rq; /*max # of outstanding pkts in receive queue*/
+
+ IB_rkey_t l_key; /*my l_key for memory regions*/
+ VAPI_qkey_t qkey; /*my qkey*/
+
+ EVAPI_compl_handler_hndl_t rq_cq_eventh, sq_cq_eventh; /* event handlers for polling */
+
+ bool is_sqp; /* relate to union below - my QP*/
+ union {
+ VAPI_special_qp_t sqp_type;
+ VAPI_qp_num_t qp_num;
+ } qp_id;
+ void *wait_q;
+} osmt_mtl_mad_res_t;
+
+
+/* init an osmt_mtl_mad_res_t with all resources initialized (use functions below) */
+VAPI_ret_t osmt_mtl_init(
+ osmt_mtl_mad_res_t* res /*pointer to res (resources) struct*/
+ );
+VAPI_ret_t osmt_mtl_init_opened_hca(
+ osmt_mtl_mad_res_t* res /*pointer to res (resources) struct*/
+ );
+
+/* Cleanup all resources of (which are valid) in res */
+VAPI_ret_t osmt_mtl_mad_cleanup(
+ osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/
+ );
+
+
+/* create CQs and QP as given in res->is_sqp (if TRUE, get special QP) */
+VAPI_ret_t osmt_mtl_get_qp_resources(
+ osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/
+);
+
+
+/* move QP to RTS state */
+VAPI_ret_t osmt_mtl_mad_qp_init(
+ osmt_mtl_mad_res_t *res /*max number of outstanding packets allowed in send queue*/
+ );
+
+
+/* create and register res->buf_ptr */
+VAPI_ret_t osmt_mtl_mad_create_mr(
+ osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/
+ );
+
+VAPI_ret_t osmt_mtl_create_av(
+ osmt_mtl_mad_res_t* res, /* pointer to res (resources) struct*/
+ int16_t dlid, /*destination lid */
+ VAPI_ud_av_hndl_t *avh_p /* address vectr handle to update */
+);
+
+/* Send MAD to given dest QP*/
+VAPI_ret_t osmt_mtl_mad_send(
+ osmt_mtl_mad_res_t* res, /*pointer to res (resources) struct*/
+ VAPI_wr_id_t id, /*wqe ID*/
+ void* mad, /*mad buffer to send*/
+ VAPI_qp_num_t dest_qp, /*destination QP*/
+ IB_sl_t sl, /*Service Level*/
+ u_int32_t dest_qkey, /*Destination QP KEY*/
+ VAPI_ud_av_hndl_t avh /* address vectr handle to use */
+);
+
+
+/* post buffers to RQ. returns num of buffers actually posted */
+int osmt_mtl_mad_post_recv_bufs(
+ osmt_mtl_mad_res_t* res, /*pointer to res (resources) struct*/
+ void *buf_array, /*array of receive buffers*/
+ u_int32_t num_o_bufs, /*number of receive buffers*/
+ u_int32_t size, /* size of expected receive packet - MAD*/
+ VAPI_wr_id_t start_id /* start id for receive buffers*/
+);
+
+
+/* Poll given CQ for completion max_poll times (POLL_SLEEP [usec] delays). result in wc_desc_p. */
+#ifndef __KERNEL__
+VAPI_ret_t osmt_mtl_mad_poll4cqe(
+ VAPI_hca_hndl_t hca, /*handle for HCA*/
+ VAPI_cq_hndl_t cq, /*handle for Completion Queue - Rcv/Send */
+ VAPI_wc_desc_t *wc_desc_p, /*handle of cqe */
+ u_int32_t max_poll, /*number of polling iterations*/
+ u_int32_t poll_sleep, /*timeout for each polling */
+ VAPI_ud_av_hndl_t *avh_p /* address vectopr handle to cleanup */
+ );
+#endif
+
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Implementation of Multicast Member testing flow..
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+/* next error code: 16A */
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+#ifdef OSM_VENDOR_INTF_MTL
+#include "osmt_inform.h"
+#endif
+
+
+static
+cl_status_t
+__match_mgids(
+ IN const void* const p_object,
+ IN void* context )
+{
+ ib_gid_t* p_mgid_context = (ib_gid_t *)context;
+ ib_gid_t* p_mgid_list_item = (ib_gid_t*)p_object;
+ int32_t count;
+
+
+ count = cl_memcmp(
+ p_mgid_context,
+ p_mgid_list_item,
+ sizeof(ib_gid_t));
+
+ if(count == 0)
+ return CL_SUCCESS;
+ else
+ return CL_NOT_FOUND;
+
+}
+
+ib_api_status_t
+osmt_query_mcast( IN osmtest_t * const p_osmt ) {
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ osmtest_req_context_t context;
+ ib_member_rec_t *p_rec;
+ uint32_t i,num_recs = 0;
+ cl_list_t mgids_list;
+ cl_list_t* p_mgids_list;
+ cl_list_iterator_t p_mgids_res;
+ cl_status_t cl_status;
+ cl_map_item_t *p_item,*p_next_item;
+ osmtest_mgrp_t *p_mgrp;
+
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_query_mcast );
+ /*
+ * Do a blocking query for all Multicast Records in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+
+ context.p_osmt = p_osmt;
+ user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ user.comp_mask = 0;
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0203: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0264: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ /* ok we have got something */
+ /* First Delete the old MGID Table */
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_qmap_remove_item(&p_osmt->exp_subn.mgrp_mlid_tbl,p_item);
+ cl_free( p_item );
+
+ }
+
+ cl_list_construct(&mgids_list);
+ cl_list_init( &mgids_list, num_recs );
+ p_mgids_list = &mgids_list;
+ num_recs = context.result.result_cnt;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_query_mcast: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec =
+ osmv_get_query_result( context.result.p_result_madw, i );
+ p_mgids_res = cl_list_find_from_head ( p_mgids_list,__match_mgids,&(p_rec->mgid));
+ /* If returns iterator other than end of list - same mgid exist already */
+ if( p_mgids_res != cl_list_end( p_mgids_list ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0203: "
+ "MCG MGIDS are the same - invalid MGID : 0x% "
+ PRIx64 " 0x% " PRIx64 "\n" ,
+ cl_ntoh64(p_rec->mgid.unicast.prefix) ,
+ cl_ntoh64(p_rec->mgid.unicast.interface_id));
+ status = IB_ERROR;
+ goto Exit;
+
+ }
+ osm_dump_mc_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ cl_status = cl_list_insert_head(p_mgids_list,&(p_rec->mgid));
+ if (cl_status)
+ {
+ osm_log( &p_osmt->log , OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0205: "
+ "Could not add MGID to cl_list.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ p_mgrp = (osmtest_mgrp_t*)cl_malloc( sizeof(*p_mgrp) );
+ if (!p_mgrp)
+ {
+ osm_log( &p_osmt->log , OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0204: "
+ "Could not allocate MCG new.\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ cl_memcpy(&p_mgrp->mcmember_rec,p_rec,sizeof(p_mgrp->mcmember_rec));
+ cl_qmap_insert(&p_osmt->exp_subn.mgrp_mlid_tbl,
+ cl_ntoh16(p_rec->mlid),&p_mgrp->map_item);
+ }
+
+
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/* given a multicast request send and wait for response. */
+ib_api_status_t
+osmt_send_mcast_request( IN osmtest_t * const p_osmt,
+ IN uint8_t is_set,
+ IN ib_member_rec_t *p_mc_req,
+ IN uint64_t comp_mask,
+ OUT ib_sa_mad_t *p_res
+ ) {
+ osmtest_req_context_t context;
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_send_mcast_request );
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( p_res, sizeof(ib_sa_mad_t ) );
+
+
+ context.p_osmt = p_osmt;
+
+ user.p_attr = p_mc_req;
+ user.comp_mask = comp_mask;
+
+ if (is_set == 1)
+ {
+ req.query_type = OSMV_QUERY_UD_MULTICAST_SET;
+ } else if (is_set == 0) {
+ req.query_type = OSMV_QUERY_UD_MULTICAST_DELETE;
+ } else if (is_set == 0xee) {
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_send_mcast_request: Set USER DEFINED QUERY\n");
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ user.method = IB_MAD_METHOD_GET;
+ user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ } else if (is_set == 0xff)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_send_mcast_request: Set USER DEFINED QUERY\n");
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ user.method = IB_MAD_METHOD_SET;
+ user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ }
+
+ /* TODO : Check the validity of all user fields in order to use
+ OSMV_QUERY_USER_DEFINED
+ p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+ if (p_user_query->method) sa_mad_data.method = p_user_query->method;
+ sa_mad_data.attr_offset = p_user_query->attr_offset;
+ sa_mad_data.attr_id = p_user_query->attr_id;
+ sa_mad_data.comp_mask = p_user_query->comp_mask;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ */
+
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_send_mcast_request: ERR 0205: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /* ok it worked */
+ cl_memcpy(p_res,
+ osm_madw_get_mad_ptr(context.result.p_result_madw),
+ sizeof(ib_sa_mad_t));
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_send_mcast_request: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.p_result_madw ) ) );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+
+}
+
+
+void
+osmt_init_mc_query_rec(IN osmtest_t * const p_osmt,
+ IN OUT ib_member_rec_t *p_mc_req) {
+ /* use default values so we can change only what we want later */
+ cl_memclr(p_mc_req,sizeof(ib_member_rec_t));
+
+ /* we leave the MGID to the user */
+ cl_memcpy(&p_mc_req->port_gid.unicast.interface_id ,
+ &p_osmt->local_port.port_guid,
+ sizeof(p_osmt->local_port.port_guid)
+ );
+
+ /* use our own subnet prefix: */
+ p_mc_req->port_gid.unicast.prefix = CL_HTON64(0xFE80000000000000ULL);
+
+ /* ib_net32_t qkey; */
+ /* ib_net16_t mlid; - we keep it zero for upper level to decide. */
+ /* uint8_t mtu; - keep it zero means - anything you have please. */
+ /* uint8_t tclass; can leave as zero for now (between subnets) */
+ /* ib_net16_t pkey; leave as zero */
+ p_mc_req->rate = IB_LINK_WIDTH_ACTIVE_4X;
+ /* uint8_t pkt_life; zero means greater than zero ... */
+ /* ib_net32_t sl_flow_hop; keep it all zeros */
+ /* we want to use a link local scope: 0x02 */
+ p_mc_req->scope_state = ib_member_set_scope_state(0x02, 0);
+}
+
+/***********************************************************************
+ * UD Multicast testing flow:
+ * o15.0.1.3:
+ * - Request new MCG with not enough components in comp_mask :
+ * ERR_INSUFFICIANT_COMPONENTS
+ * o15.0.1.8:
+ * - Request a join with irrelevant RATE and get a ERR_INVALID_REQ
+ * o15.0.1.4:
+ * - Create an MGID by asking for a join with MGID = 0
+ * providing P_Key, Q_Key, SL, FlowLabel, Tclass.
+ * o15.0.1.5:
+ * - Check the returned MGID is valid. (p 804)
+ * o15.0.1.6:
+ * - Create a new MCG with valid requested MGID.
+ * - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID
+ * - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?)
+ * - Try to create again the already created group: ERR_REQ_INVALID
+ * o15.0.1.7 - implicitlly checked during the prev steps.
+ * o15.0.1.9
+ * - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID
+ * o15.0.1.10 - can't check on a single client .
+ * o15.0.1.11:
+ * - Try to join into a MGID that exists with JoinState=SendOnlyMember -
+ * see that it updates JoinState. What is the routing change?
+ * - We can not check simple join since we have only one tester (for now)
+ * o15.0.1.12:
+ * - The last join should have a special treatment in the SA (sender only)
+ * but what is it ?
+ * o15.0.1.13:
+ * - Try joining with wrong rate - ERR_REQ_INVALID
+ * o15.0.1.14:
+ * - Try partial delete - actually updating the join state. check it.
+ * - Register by InformInfo flow to receive trap 67 on MCG delete.
+ * - Try full delete (JoinState and should be 0)
+ * - Wait for trap 67.
+ * - Try joining (not full mem) again to see the group was deleted.
+ * (should fail)
+ * o15.0.1.15:
+ * - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID
+ * o15.0.1.16:
+ * - Try GetTable with PortGUID wildcarded and get back some groups.
+ ***********************************************************************/
+ib_api_status_t
+osmt_run_mcast_flow( IN osmtest_t * const p_osmt ) {
+ ib_api_status_t status;
+ ib_member_rec_t mc_req_rec;
+ ib_member_rec_t *p_mc_res;
+ ib_sa_mad_t res_sa_mad;
+ uint64_t comp_mask=0;
+ ib_net64_t remote_port_guid=0x0;
+ cl_qmap_t *p_mgrp_mlid_tbl;
+ osmtest_mgrp_t *p_mgrp;
+ ib_gid_t special_mgid,tmp_mgid,proxy_mgid;
+ ib_net16_t invalid_mlid=0x0;
+ ib_net16_t max_mlid = cl_hton16(0xFFFE),tmp_mlid;
+ boolean_t ReachedMlidLimit = FALSE;
+ int start_cnt=0,cnt,middle_cnt=0,end_cnt=0;
+ int IPoIBIsFound=0,mcg_outside_test_cnt=0,fail_to_delete_mcg=0;
+ osmtest_req_context_t context;
+ ib_node_record_t *p_rec;
+ uint32_t num_recs = 0,i;
+ uint8_t mtu_phys = 0,rate_phys = 0;
+
+
+ static ib_gid_t good_mgid = {
+ {
+ 0xFF, 0x12, 0xA0, 0x1C,
+ 0xFE, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x34, 0x56, 0x78
+ }
+ };
+ static ib_gid_t osm_ipoib_mgid = {
+ {
+ 0xff, /* multicat field */
+ 0x12, /* scope */
+ 0x40, 0x1b, /* IPv4 signature */
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+ 0xff, 0xff, 0xff, 0xee, /* 32 bit IPv4 broadcast address */
+ },
+ };
+
+ static ib_gid_t osm_ts_ipoib_good_mgid = {
+ {
+ 0xff, /* multicast field */
+ 0x12, /* non-permanent bit,scope */
+ 0x40, 0x1b, /* IPv4 signature */
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+ 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */
+ },
+ };
+ static ib_gid_t osm_ipoib_good_mgid = {
+ {
+ 0xff, /* multicast field */
+ 0x12, /* non-permanent bit,scope */
+ 0x40, 0x1b, /* IPv4 signature */
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+ 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */
+ },
+ };
+ static ib_gid_t osm_link_local_mgid = {
+ {
+ 0xFF, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01
+ },
+ };
+
+
+#ifdef OSM_VENDOR_INTF_MTL
+ ib_inform_info_t inform_info;
+ osmt_qp_ctx_t qp_ctx;
+#endif
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_run_mcast_flow );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "GetTable of all current MCG ...\n"
+ );
+ status = osmt_query_mcast( p_osmt );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 2FF "
+ "GetTable of all records has failed!\n");
+ goto Exit;
+
+ }
+
+ p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* Only when we are on single mode check flow - do the count comparison , otherwise skip */
+ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+ {
+ start_cnt = cl_qmap_count(p_mgrp_mlid_tbl);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow (start): "
+ "Number of MC Records found at SA DB is %d.\n",start_cnt);
+ }
+
+ /* This flow is being added due to bug discovered using Infinicon stack -
+ The bug was initializing MCast with MTU & RATE min values that does
+ not match the subnet capability , even though that OpenSM
+ reposnds with the correct value it does not store it in the MCG.
+ We want the check a join request to already existing group (ipoib)
+ without using MTU or RATE then getting respond from OpenSM with
+ the correct values then join again with them and get IB_SUCCESS
+ all the way
+ */
+
+ /* First validate IPoIB exist in the SA DB */
+ p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl );
+ /* scan all available multicast groups in the DB and fill in the table */
+ while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) )
+ {
+ /* search for ipoib mgid */
+ if (!cl_memcmp(&osm_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ipoib_good_mgid)) ||
+ !cl_memcmp(&osm_ts_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ts_ipoib_good_mgid)))
+ {
+ IPoIBIsFound=1;
+ }
+ else
+ mcg_outside_test_cnt++;
+
+ p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ if (IPoIBIsFound)
+ {
+ /* o15-0.2.4 - Check a join request to already created MCG */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Found IPoIB MC Group , so we run Infinicon Bug Flow ...\n");
+ /* Try to join first like IPoIB of Infinicon */
+ cl_memcpy(&mc_req_rec.mgid,&osm_ipoib_good_mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+
+ status = osmt_send_mcast_request(
+ p_osmt, 0xff, /* User Defined query Set */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Sent Join request with :\n\t\tport_gid=0x%016"PRIx64
+ ":0x%016" PRIx64 " , mgid=0x%016" PRIx64 ":0x%016" PRIx64
+ "\n\t\tjoin state= 0x%x, response is : %s\n" ,
+ cl_ntoh64(mc_req_rec.port_gid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id),
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+ (mc_req_rec.scope_state & 0x0F),
+ ib_get_err_str(status));
+ /* Check MTU & Rate Value and resend with SA suggested values */
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* Prepare the mc_req_rec for the rest of the flow */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /*
+ We simulate the same situation as in Infinicon - a response with the
+ exact RATE & MTU as the SA responded with. Actually the query
+ has included some more fields but we know that problem was
+ genereated by the RATE
+ */
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Received attributes of MCG : \n\t\tMTU=0x%02X , RATE=0x%02X\n"
+ ,p_mc_res->mtu,p_mc_res->rate);
+
+ mc_req_rec.mtu = p_mc_res->mtu ;
+ mc_req_rec.rate = p_mc_res->rate ;
+ /* Set mtu & rate phhysible that will allow check the
+ exact statement of OpenSM */
+ mtu_phys = p_mc_res->mtu ;
+ rate_phys = p_mc_res->rate ;
+
+ cl_memcpy(&mc_req_rec.mgid,&osm_ipoib_good_mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU |
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Sending attributes of MCG : \n\t\tMTU=0x%02X , RATE=0x%02X\n"
+ ,mc_req_rec.mtu,mc_req_rec.rate);
+ status = osmt_send_mcast_request( p_osmt, 0xff, /* User Defined query */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Sent Join request using response values , response is : %s\n"
+ ,ib_get_err_str(status));
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ee : "
+ "Query as Full Member of already existing ipoib group 0x%016"
+ PRIx64 ":0x%016" PRIx64 " has failed\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ goto Exit;
+ }
+ else
+ {
+ mtu_phys = 0 ;
+ rate_phys = 0 ;
+ }
+ /* We do not want to leave the MCG since its IPoIB */
+ }
+
+ /**************************************************************************/
+ /* Check Get with invalid mlid */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Get with invalid mlid ...\n"
+ );
+ /* Request Get */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ mc_req_rec.mlid = invalid_mlid;
+ comp_mask =
+ IB_MCR_COMPMASK_MLID;
+
+ status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E0 "
+ "Succceed SubnAdmGet with invalid mlid 0x%x.\n",
+ cl_ntoh16(mc_req_rec.mlid));
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Prepare the mc_req_rec for the rest of the flow */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /**************************************************************************/
+ /* Check Get with invalid port guid */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Get with invalid port guid (0x0) but valid interface ID : 0x%"
+ PRIx64 " ...\n",
+ cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id));
+
+ /* Request Get */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ cl_memclr(&mc_req_rec.port_gid.unicast.interface_id,sizeof(ib_net64_t));
+ comp_mask =
+ IB_MCR_COMPMASK_GID;
+
+ status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E4 "
+ "Succceed SubnAdmGet with invalid port guid .\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Prepare the mc_req_rec for the rest of the flow */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /**************************************************************************/
+
+ /* o15.0.1.3: */
+ /* - Request Join with insufficiant comp_mask */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficiant comp mask qkey & pkey (o15.0.1.3)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ /* IB_MCR_COMPMASK_QKEY | */
+ /* IB_MCR_COMPMASK_PKEY | intentionaly missed to raise the error */
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficiant comp mask - sl (15.0.1.3)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec,IB_MC_REC_STATE_FULL_MEMBER );
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ /* IB_MCR_COMPMASK_SL | */
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+
+ mc_req_rec.mgid.raw[15] = 0x01;
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficiant comp mask - flow label (o15.0.1.3)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ /* IB_MCR_COMPMASK_FLOW | intentionaly missed to raise the error */
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficiant comp mask - tclass (o15.0.1.3)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER) ;
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ /* IB_MCR_COMPMASK_TCLASS | Intentionally missed to raise an error */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficiant comp mask - tclass qkey (o15.0.1.3)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ /* no MGID */
+ /* cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t)); */
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ /* IB_MCR_COMPMASK_QKEY | intentionaly missed to raise the error */
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ /* IB_MCR_COMPMASK_TCLASS | intentionaly missed to raise the error */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+#if 0
+ /* CURRENTLY NOT SUPPORTED !!!! "Unrealizable" condition not available by OSM */
+
+ /* o15.0.1.8: */
+ /* - Request join with irrelevant RATE : get a ERR_INSUFFICIANT_COMPONENTS */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic rate (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_12X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Check Valid value which is unreasonable now */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic rate 30GB (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.rate =
+ IB_PATH_RECORD_RATE_30_GBS |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+ /* Check Valid value which is unreasonable now */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with less then min rate 2.5GB (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.rate =
+ IB_PATH_RECORD_RATE_2_5_GBS |
+ IB_PATH_SELECTOR_LESS_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ab: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+
+
+
+ /* Checking above max value of MTU which is impossible */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic mtu (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested mtu */
+ mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic mtu (o15.0.1.8)...\n"
+ );
+/* Checking above max value of MTU which is impossible */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic mtu : \n\t\tless then 256 -"
+ " min (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested mtu */
+ mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic mtu (o15.0.1.8)...\n"
+ );
+
+
+ /* impossible requested mtu */
+ mc_req_rec.mtu = 0x6 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Check PacketLifeTime as 0 */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create with un-realistic packet life value less than 0 (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_LIFE |
+ IB_MCR_COMPMASK_LIFE_SEL;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0207: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+#endif
+
+ /* o15.0.1.4: */
+ /* - Create an MGID by asking for a join with MGID = 0 */
+ /* providing P_Key, Q_Key, SL, FlowLabel, Tclass. */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip service level (o15.0.1.4)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ /* IB_MCR_COMPMASK_SL | Intentionally missed */
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Check that no same MCG in the SMDB */
+ status = osmt_query_mcast( p_osmt);
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02aa: "
+ "Could not get all MC Records in subnet , got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Only when we are on single mode check flow - do the count comparison , otherwise skip */
+ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+ {
+ middle_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow (post false create): "
+ "Number of MC Records found at SA DB is %d.\n",middle_cnt);
+ if (middle_cnt != start_cnt)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ab: "
+ "Got different number of records stored in SA DB (before any creation)\n"
+ "Instead of %d got %d.\n",start_cnt,middle_cnt);
+ status=IB_ERROR;
+ goto Exit;
+ }
+ }
+
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ /* IB_MCR_COMPMASK_QKEY | */
+ /* IB_MCR_COMPMASK_PKEY | Intentionally missed */
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Bad Query o15.0.1.4 */
+
+ status = osmt_query_mcast( p_osmt);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip Tclass (o15.0.1.4)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ /* IB_MCR_COMPMASK_TCLASS | Intentionally missed */
+ /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0206: "
+ "Expecetd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 valid Set several options :\n\t\t"
+ "First above min RATE , Second less then max RATE \n\t\t"
+ "Third above min MTU , Second less then max MTU \n\t\t"
+ "Fifth exact MTU & RATE physible , Sixth exact RATE physible\n\t\t"
+ "Seventh exact MTU physible (o15.0.1.4)...\n"
+ );
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0208: "
+ "Fail to create MGC for MGID=0 with higher then minimum RATE.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_12X |
+ IB_PATH_SELECTOR_LESS_THAN << 6;
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 020ab: "
+ "Fail to create MGC for MGID=0 with less then highest RATE.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+ mc_req_rec.mtu = IB_MTU_LEN_4096 |
+ IB_PATH_SELECTOR_LESS_THAN << 6;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0238: "
+ "Fail to create MGC for MGID=0 with less then highest MTU.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+ mc_req_rec.mtu = IB_MTU_LEN_256 |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0239: "
+ "Fail to create MGC for MGID=0 with higher then lowest MTU.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+ /* Using Exact physible MTU & RATE */
+
+ mc_req_rec.mtu = mtu_phys;
+ mc_req_rec.rate = rate_phys;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU |
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0240: "
+ "Fail to create MGC for MGID=0 with exact MTU & RATE.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+ /* Using Exact physible RATE */
+
+ mc_req_rec.rate = rate_phys;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0241: "
+ "Fail to create MGC for MGID=0 with exact RATE.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+ /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+ /* Using Exact physible MTU */
+
+ mc_req_rec.mtu = mtu_phys;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0240: "
+ "Fail to create MGC for MGID=0 with exact MTU.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+
+ /* o15.0.1.5: */
+ /* - Check the returned MGID is valid. (p 804) */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating resulting MGID (o15.0.1.5)...\n"
+ );
+ /* prefix 0xFF1 Scope 0xA01B */
+ /* Since we did not directly specified SCOPE in comp mask
+ we should get the comp mask that is link-local scope */
+ if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) ||
+ (p_mc_res->mgid.multicast.header[1] != 0x12) ||
+ (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+ (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1B) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0209: "
+ "Validating MGID failed. MGID:0x%016" PRIx64 "\n",
+ p_mc_res->mgid
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Lets try another multicast request */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 (o15.0.1.4)...\n"
+ );
+ status = osmt_query_mcast( p_osmt);
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* no MGID */
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+ mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_LIFE |
+ IB_MCR_COMPMASK_LIFE_SEL;
+
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0208: "
+ "Fail to create MGC for MGID=0.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* o15.0.1.6: */
+ /* - Create a new MCG with valid requested MGID. */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " (o15.0.1.6)...\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+ mc_req_rec.mgid = good_mgid;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC for MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " (o15.0.1.6)...\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad)),
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id));
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating resulting MGID (o15.0.1.6)...\n"
+ );
+ /* prefix 0xFF1 Scope 0xA01B */
+ if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) ||
+ (p_mc_res->mgid.multicast.header[1] != 0x12) || /* HACK hardcoded scope = 0x02 */
+ (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+ (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1C) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0211: "
+ "Validating MGID failed. MGID:0x%016" PRIx64 "\n",
+ p_mc_res->mgid
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MGID=0xFA..... (o15.0.1.6)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ mc_req_rec.mgid.raw[0] = 0xFA;
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0212: "
+ "Fail to recognize MGID error for MGID=0xFA......\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MGID=0xFF12A01B..... with link-local scope (o15.0.1.6)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ mc_req_rec.mgid.raw[0] = 0xFF;
+ mc_req_rec.mgid.raw[3] = 0x1B;
+ comp_mask = comp_mask | IB_MCR_COMPMASK_SCOPE;
+ mc_req_rec.scope_state = mc_req_rec.scope_state & 0x2F; /* local scope */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0213: "
+ "Fail to recognize MGID error for A01B with link-local bit (status %s) (rem status %s)\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Change the mgid prefix - get back ERR_REQ_INVALID */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MGID PREFIX=0xEF... (o15.0.1.6)...\n"
+ );
+
+
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+
+ mc_req_rec.mgid = good_mgid;
+
+ mc_req_rec.mgid.raw[0] = 0xEF;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0212: "
+ "Fail to recognize MGID PREFIX error for MGID=0xEF....\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+
+
+ /* Change the scope to reserved - get back VALID REQ */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking local scope with full member \n\t\tand valid mgid 0x%016"
+ PRIx64 ":0x%016" PRIx64 " ... (o15.0.1.6)...\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ mc_req_rec.mgid = good_mgid;
+
+ mc_req_rec.mgid.raw[1] = 0x1F;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC for MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 ".\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ),
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id));
+ goto Exit;
+ }
+
+
+ /* Change the flags to invalid value 0x2 - get back INVALID REQ */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking invalid flags=0xFF 22 ... (o15.0.1.6)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+
+ mc_req_rec.mgid = good_mgid;
+
+ mc_req_rec.mgid.raw[1] = 0x22;
+
+
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0214: "
+ "Fail to recognize create with invalid flags value 0x2\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ /* Change the MGID to link local MGID - get back VALID REQ */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking link local MGID 0xFF02:0:0:0:0:0:0:1 (o15.0.1.6)...\n"
+ );
+
+ mc_req_rec.mgid = osm_link_local_mgid;
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC for MGID=0xFF02:0:0:0:0:0:0:1.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+ /* o15.0.1.7 - implicitlly checked during the prev steps. */
+ /* o15.0.1.8 - implicitlly checked during the prev steps. */
+
+ /* o15.0.1.9 */
+ /* - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.mgid.raw[12] = 0xFF;
+ mc_req_rec.scope_state = 0x22; /* link-local scope */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0214: "
+ "Fail to recognize create with JoinState != FullMember\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+
+ /* Lets try a valid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+ );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.scope_state = 0x23; /* link-local scope , non member and full member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC with valid join state 0x3.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+
+
+ /* Lets try another invalid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ /* We have created a new MCG so now we need different mgid when cresting group otherwise it will be counted as join request .*/
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.mgid.raw[12] = 0xFC;
+
+ mc_req_rec.scope_state = 0x24; /* link-local scope , send only member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0214: "
+ "Fail to recognize create with JoinState != FullMember\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Lets try another valid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with valid join state (o15.0.1.9)...\n"
+ );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.mgid.raw[12] = 0xFB;
+ cl_memcpy(&special_mgid , &mc_req_rec.mgid ,sizeof(ib_gid_t));
+ mc_req_rec.scope_state = 0x2F; /* link-local scope , Full member with all other bits turned on */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC with valid join state 0xF\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* o15.0.1.10 - can't check on a single client .-- obsolete -
+ checked by Infinicon bug o15-0.2.4 , never the less recheck */
+ /* o15-0.2.4 - Check a join request to already created MCG */
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Check o15-0.2.4 statement ...\n");
+ /* Try to join */
+ cl_memcpy(&mc_req_rec.mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+ /* Request Join */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER);
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+
+ status = osmt_send_mcast_request( p_osmt, 0x1, /* User Defined query */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02cc: "
+ "Fail to join MGC with valid req , returned status = %s\n",
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ goto Exit;
+ }
+
+
+ /* o15.0.1.11: */
+ /* - Try to join into a MGID that exists with JoinState=SendOnlyMember - */
+ /* see that it updates JoinState. What is the routing change? */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n"
+ );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.scope_state = 0x22; /* link-local scope, send only member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0215: "
+ "Fail to update existing MGID\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update with NonMember (o15.0.1.11)...\n"
+ );
+
+ if (p_mc_res->scope_state != 0x23) /* scope is LSB */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0216: "
+ "Validating JoinState update failed. Expected 0x23 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Try delete current join state then update it with another value */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking JoinState update request should return 0x22 (o15.0.1.11)...\n"
+ );
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.mgid = good_mgid;
+ /* link-local scope, non member (so we should not be able to delete) */
+ /* but the FullMember bit should be gone */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Partially delete JoinState (o15.0.1.14)...\n"
+ );
+ mc_req_rec.scope_state = 0x22;
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+
+ if ((status != IB_SUCCESS) || (p_mc_res->scope_state != 0x21))
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0218: "
+ "Fail to partially update JoinState : %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* So far delete succeffully state - Now change it*/
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0215: "
+ "Fail to update existing MCG\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update with Send Only Member (o15.0.1.11)...\n"
+ );
+
+ if (p_mc_res->scope_state != 0x25) /* scope is MSB */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0216: "
+ "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ /* Now try to update value of join state */
+ mc_req_rec.scope_state = 0x21; /* link-local scope, full member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0215: "
+ "Fail to update existing MGID\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update with Full Member\n\t\t"
+ "to an existing 0x5 state MCG (o15.0.1.11)...\n");
+
+ if (p_mc_res->scope_state != 0x25) /* scope is LSB */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0216: "
+ "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Now try to update value of join state */
+ mc_req_rec.scope_state = 0x22; /* link-local scope,non member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0215: "
+ "Fail to update existing MGID\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update with Non Member\n\t\t"
+ "to an existing 0x5 state MCG (o15.0.1.11)...\n");
+
+ if (p_mc_res->scope_state != 0x27) /* scope is LSB */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0216: "
+ "Validating JoinState update failed. Expected 0x27 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "DEBUG - Current scope_state value : 0x%02X...\n", p_mc_res->scope_state);
+
+ /* - We can not check simple join since we have only one tester (for now) */
+
+ /* o15.0.1.12: Not Supported*/
+ /* - The SendOnlyNonMem join should have a special treatment in the
+ SA but what is it ? */
+
+ /* o15.0.1.13: */
+ /* - Try joining with rate that does not exist in any MCG -
+ ERR_REQ_INVALID */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n"
+ );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_LESS_THAN << 6;
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0217: "
+ "Fail to catch BAD RATE joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Try MTU that does not exist in any MCG */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MTU (higher them max) when connecting to "
+ "existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ mc_req_rec.mgid = osm_ipoib_mgid;
+ mc_req_rec.mtu =
+ IB_MTU_LEN_4096 |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0217: "
+ "Fail to catch BAD RATE (higher them max) joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Try another MTU that does not exist in any MCG */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MTU (less then min) when connecting "
+ "to existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ mc_req_rec.mgid = osm_ipoib_mgid;
+ mc_req_rec.mtu =
+ IB_MTU_LEN_256 |
+ IB_PATH_SELECTOR_LESS_THAN << 6;
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02cd: "
+ "Fail to catch BAD RATE (less them min) joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+
+
+ /* o15.0.1.14: */
+ /* - Try partial delete - actually updating the join state. check it. */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking partial JoinState delete request - removing NonMember (o15.0.1.14)...\n"
+ );
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.mgid = good_mgid;
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+
+ /* link-local scope, non member (so we should not be able to delete) */
+ /* but the FullMember bit should be gone */
+ mc_req_rec.scope_state = 0x22;
+
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0218: "
+ "Fail to partially update JoinState during delete: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State removal of Non Member bit (o15.0.1.14)...\n"
+ );
+ if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only the non member & send only member have left */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0219: "
+ "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+
+ /* Now use the same scope_state and delete all JoinState - leave multicast group since state is 0x0 */
+
+ mc_req_rec.scope_state = 0x25;
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0218: "
+ "Fail to update JoinState during delete: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update remove (o15.0.1.14)...\n"
+ );
+
+ if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only 0x0 so port is removed from MCG */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0219: "
+ "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+ p_mc_res->scope_state
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* - Try joining (not full mem) again to see the group was deleted. (should fail) */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Delete by trying to Join deleted group (o15.0.1.14)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ mc_req_rec.scope_state = 0x22; /* use non member - so if no group fail */
+ status = osmt_send_mcast_request( p_osmt, 1, /* join */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status != IB_REMOTE_ERROR)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0221: "
+ "Succeeded Joining Deleted Group: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+
+ /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ mc_req_rec.mgid = osm_ipoib_mgid;
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.scope_state = 0x21; /* delete full member */
+
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0222: "
+ "Fail to catch BAD delete from IPoIB: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Prepare another MCG for the following tests : */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n\t\t(o15.0.1.4)...\n",
+ cl_ntoh64(osm_ipoib_mgid.unicast.prefix),
+ cl_ntoh64(osm_ipoib_mgid.unicast.interface_id));
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.mgid.raw[12] = 0xAA;
+ mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.scope_state = 0x21;/* Full memeber */
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_LIFE |
+ IB_MCR_COMPMASK_LIFE_SEL;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0210: "
+ "Fail to create MGC for 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 ".\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ),
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id));
+ goto Exit;
+ }
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+ /* - Register by InformInfo flow to receive trap 67 on MCG delete. */
+ /* bind the QP */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Setting InformInfo for Trap 67 (o15.0.1.14)...\n"
+ );
+ status = osmt_bind_inform_qp( p_osmt, &qp_ctx);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* init the inform info */
+ osmt_init_inform_info(p_osmt, &inform_info);
+
+ /* limit to trap 67 from SM */
+ inform_info.lid_range_begin = cl_ntoh16(p_osmt->local_port.sm_lid);
+ inform_info.lid_range_end = cl_ntoh16(p_osmt->local_port.sm_lid);
+ inform_info.g_or_v.generic.trap_num = cl_hton16(67);
+
+ /* send the inform info registration */
+ status = osmt_reg_unreg_inform_info(p_osmt,
+ &qp_ctx,
+ &inform_info,
+ 1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+
+ /*--------------------- PREP -------------------------*/
+ if (osmt_mtl_mad_post_recv_bufs(
+ &qp_ctx.qp_bind_hndl,
+ qp_ctx.p_recv_buf,
+ 1, /* we need to reveive the report */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ 1) != 1) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0127: "
+ "Error posting recv bufs .\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_run_mcast_flow: "
+ "Posted recv bufs .\n");
+
+#endif /* OSM_VENDOR_INTF_MTL */
+
+ /* - Try delete with valid join state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Full Delete of a group (o15.0.1.14)...\n"
+ );
+ mc_req_rec.scope_state = 0x21; /* the FullMember is the current JoinState */
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+ /* - Wait for trap 67. */
+ status = osmt_trap_wait( p_osmt, &qp_ctx);
+
+ /* cleanup */
+ osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+#endif
+
+
+ /* o15.0.1.15: */
+ /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+
+ mc_req_rec.mgid = osm_ipoib_mgid;
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.scope_state = 0x21; /* delete full member */
+
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0223: "
+ "Fail to catch BAD delete from IPoIB: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /**************************************************************************/
+ /* Checking join with invalid MTU */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with un-realistic mtu : \n"
+ "\t\tFirst create new MCG then try to join it \n"
+ "\t\twith unrealistic MTU greater then 4096 (o15.0.1.8)...\n"
+ );
+
+ /* First create new mgrp */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ mc_req_rec.mtu = IB_MTU_LEN_1024 | IB_PATH_SELECTOR_EXACTLY << 6;
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS | /* all above are required */
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ea "
+ "Failed to create new mgrp.\n");
+ goto Exit;
+ }
+ cl_memcpy(&tmp_mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+ osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_INFO );
+ /* tmp_mtu = p_mc_res->mtu & 0x3F; */
+
+
+ /* impossible requested mtu always greater then exist in MCG */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+ );
+ mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+ cl_memcpy(&mc_req_rec.mgid,&tmp_mgid,sizeof(ib_gid_t));
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+ comp_mask =
+ IB_MCR_COMPMASK_GID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_MTU_SEL |
+ IB_MCR_COMPMASK_MTU;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: "
+ " Expected Errors: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ );
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02e4: "
+ "Expecetd REMOTE ERROR got:%s/%s.\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* - Try GetTable with PortGUID wildcarded and get back some groups. */
+ status = osmt_query_mcast( p_osmt);
+ cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow (Before checking Max MCG creation): "
+ "Number of MC Records found at SA DB is %d.\n",cnt);
+
+ /**************************************************************************/
+ /* Checking join on behalf of remote port gid */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Proxy Join ...\n"
+ );
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0007: "
+ "osmtest_get_all_recs failed on getting all node records(%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Populate the database with the received records.
+ */
+ num_recs = context.result.result_cnt;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+ if (p_rec->node_info.port_guid != p_osmt->local_port.port_guid &&
+ p_rec->node_info.node_type == IB_NODE_TYPE_CA)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "current port_guid = 0x%" PRIx64 "\n",
+ cl_ntoh64(p_rec->node_info.port_guid));
+
+ remote_port_guid = p_rec->node_info.port_guid;
+ i = num_recs;
+ }
+ }
+
+ if (remote_port_guid != 0x0)
+ {
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+ mc_req_rec.port_gid.unicast.interface_id = remote_port_guid;
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS; /* all above are required */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02b4: "
+ "Could not join on behalf of remote port 0x%016" PRIx64
+ " remote status: %s.\n",
+ cl_ntoh64(remote_port_guid),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ cl_memcpy(&proxy_mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+
+ /* First try a bad deletion then good one */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02a9: "
+ "Succeed deletion of remote port guid with local one MGID : "
+ "0x%016" PRIx64 " : 0x%016" PRIx64 " , Got : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ mc_req_rec.mgid = proxy_mgid;
+ mc_req_rec.port_gid.unicast.interface_id = remote_port_guid;
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ab: "
+ "Failed to delete mgid with remote port guid MGID : "
+ "0x%016" PRIx64 " : 0x%016" PRIx64 " , Got : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ goto Exit;
+ }
+ }
+ else
+ {
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Could not check proxy join since could not found remote port , different from local port.\n");
+ }
+
+
+ /* prepare init for next check */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /**************************************************************************/
+ if (p_osmt->opt.mmode > 2)
+ {
+ /* Check invalid Join with max mlid which is more then the
+ Mellanox switches support 0xC000+0x1000 = 0xd000 */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Creation of Maximum avaliable Groups (MulticastFDBCap) ...\n"
+ );
+ tmp_mlid = cl_ntoh16(max_mlid) - cnt;
+
+ while (tmp_mlid > 0 && !ReachedMlidLimit) {
+ uint16_t cur_mlid = 0;
+ /* Request Set */
+ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+ /* Good Flow - mgid is 0 while giving all required fields for
+ join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ mc_req_rec.mlid = max_mlid;
+ cl_memclr(&mc_req_rec.mgid,sizeof(ib_gid_t));
+
+
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_QKEY |
+ IB_MCR_COMPMASK_PKEY |
+ IB_MCR_COMPMASK_SL |
+ IB_MCR_COMPMASK_FLOW |
+ IB_MCR_COMPMASK_JOIN_STATE |
+ IB_MCR_COMPMASK_TCLASS |/* all above are required */
+ IB_MCR_COMPMASK_MLID;
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ if (status != IB_SUCCESS)
+ {
+
+ if (cur_mlid > cl_ntoh16(max_mlid))
+ {
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E1 "
+ "Succceed Join with greater mlid then switches support (MulticastFDBCap) 0x%04X.\n",
+ cur_mlid);
+ status = IB_ERROR;
+ osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_VERBOSE );
+ goto Exit;
+ } else if (( res_sa_mad.status & IB_SMP_STATUS_MASK ) == IB_SA_MAD_STATUS_NO_RESOURCES) {
+ /* You can quitly exit the loop since no available mlid in SA DB
+ i.e. reached the maximum valiad avalable mlid */
+ ReachedMlidLimit = TRUE;
+ }
+ }
+ else
+ {
+ cur_mlid = cl_ntoh16(p_mc_res->mlid);
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow : "
+ "Added to new MCGroup with Mlid 0x04%x\n",cur_mlid);
+ }
+ tmp_mlid--;
+ }
+ }
+ /* Prepare the mc_req_rec for the rest of the flow */
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ /**************************************************************************/
+ /* o15.0.1.16: */
+ /* - Try GetTable with PortGUID wildcarded and get back some groups. */
+ status = osmt_query_mcast( p_osmt);
+ cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow (Before Deletion of all MCG): "
+ "Number of MC Records found at SA DB is %d.\n",cnt);
+
+
+
+ /* Delete all MCG that are not of IPoIB */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow : "
+ "Cleanup all MCG that are not IPoIB...\n",cnt);
+
+ p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+ p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl );
+ /* scan all available multicast groups in the DB and fill in the table */
+ while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) )
+ {
+ /* Only if different from IPoIB Mgid try to delete */
+ if (cl_memcmp(&osm_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ipoib_good_mgid)) &&
+ cl_memcmp(&osm_ts_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ts_ipoib_good_mgid)))
+ {
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+ mc_req_rec.mgid = p_mgrp->mcmember_rec.mgid;
+
+
+ /* o15-0.1.4 - need to specify the oppsite state for a valid delete */
+ if (!cl_memcmp(&special_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(special_mgid)))
+ {
+ mc_req_rec.scope_state = 0x2F;
+ }
+ else
+ {
+ mc_req_rec.scope_state = 0x21;
+ }
+ comp_mask =
+ IB_MCR_COMPMASK_MGID |
+ IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow : "
+ "Sending request to delete MGID : 0x%016" PRIx64
+ " : 0x%016" PRIx64 ", scope_state : 0x%02X.\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+ mc_req_rec.scope_state);
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02FF: "
+ "Fail to delete MGID : 0x%016" PRIx64 " : 0x%016" PRIx64
+ " ,\n\t\t it is not our MCG , Status : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ fail_to_delete_mcg++;
+ }
+ }
+ p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ status = osmt_query_mcast( p_osmt);
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 2FF "
+ "GetTable of all records has failed!\n");
+ goto Exit;
+ }
+ /* Only when we are on single mode check flow - do the count comparison , otherwise skip */
+ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+ {
+ end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow (After Deletion of all MCG): "
+ "Number of MC Records found at SA DB is %d.\n",end_cnt);
+ /* In a single mode we should treat the MCG as ours , if there are groups
+ that could not be deleted it means that an outside source has used MC (porbably
+ not from our port as well) , thus we cannot assure (in a single mode) that our
+ comparison Start vs End count is valid */
+ if (end_cnt != start_cnt && fail_to_delete_mcg == 0)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ab: "
+ "Got different number of records stored in SA DB at Start got \n\t\t"
+ " %d , at End got %d\n",
+ start_cnt,end_cnt);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "At start got %d MCG external groups (not IPoIB) , at end got %d MCG that could not be deleted \n\t\t"
+ " (registered from different port or different pkey)\n",mcg_outside_test_cnt,fail_to_delete_mcg);
+
+ status=IB_ERROR;
+ goto Exit;
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Implementation of service records testing flow..
+ * Top level is osmt_run_service_records_flow:
+ * osmt_register_service
+ * osmt_get_service_by_name
+ * osmt_get_all_services
+ * osmt_delete_service_by_name
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+/* next error code: 16A */
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+
+
+ib_api_status_t
+osmt_register_service( IN osmtest_t * const p_osmt,
+ IN ib_net64_t service_id,
+ IN ib_net16_t service_pkey,
+ IN ib_net32_t service_lease,
+ IN uint8_t service_key_lsb,
+ IN char *service_name) {
+ osmv_query_req_t req;
+ osmv_user_query_t user;
+ osmtest_req_context_t context;
+ ib_service_record_t svc_rec;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osmt_register_service );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service: "
+ "Registering Service: name:%s id:0x%" PRIx64 ".\n",
+ service_name, cl_ntoh64(service_id));
+
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+
+ /* set the new service record fields */
+ svc_rec.service_id = service_id;
+ svc_rec.service_pkey = service_pkey;
+ svc_rec.service_gid.unicast.prefix = 0;
+ svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+ svc_rec.service_lease = service_lease;
+ cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+ svc_rec.service_key[0] = service_key_lsb;
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memcpy(svc_rec.service_name, service_name,
+ (strlen(service_name)+1)*sizeof(char));
+
+ /* prepare the data used for this query */
+ /* sa_mad_data.method = IB_MAD_METHOD_SET; */
+ /* sa_mad_data.sm_key = 0; */
+
+ context.p_osmt = p_osmt;
+ req.query_context = &context;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.sm_key = 0;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+ user.method = IB_MAD_METHOD_SET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ if (ib_pkey_is_invalid(service_pkey))
+ {
+ /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME;
+ }
+ else
+ {
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SPKEY |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME;
+ }
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service: ERR 0303: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service: ERR 0364: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
+ib_api_status_t
+osmt_register_service_with_full_key ( IN osmtest_t * const p_osmt,
+ IN ib_net64_t service_id,
+ IN ib_net16_t service_pkey,
+ IN ib_net32_t service_lease,
+ IN uint8_t *service_key,
+ IN char *service_name) {
+ osmv_query_req_t req;
+ osmv_user_query_t user;
+ osmtest_req_context_t context;
+ ib_service_record_t svc_rec,*p_rec;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status;
+ uint8_t i,skey[16];
+
+ OSM_LOG_ENTER( p_log, osmt_register_service_with_full_key );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service_with_full_key: "
+ "Registering Service: name:%s id:0x%" PRIx64 ".\n",
+ service_name, cl_ntoh64(service_id));
+
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+
+ /* set the new service record fields */
+ svc_rec.service_id = service_id;
+ svc_rec.service_pkey = service_pkey;
+ svc_rec.service_gid.unicast.prefix = 0;
+ svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+ svc_rec.service_lease = service_lease;
+ cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+ cl_memcpy(svc_rec.service_key,service_key,16*sizeof(uint8_t));
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memclr(skey, 16*sizeof(uint8_t));
+ cl_memcpy(svc_rec.service_name, service_name,
+ (strlen(service_name)+1)*sizeof(char));
+
+ /* prepare the data used for this query */
+ /* sa_mad_data.method = IB_MAD_METHOD_SET; */
+ /* sa_mad_data.sm_key = 0; */
+
+ context.p_osmt = p_osmt;
+ req.query_context = &context;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.sm_key = 0;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+ user.method = IB_MAD_METHOD_SET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ if (ib_pkey_is_invalid(service_pkey))
+ {
+ /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME;
+ }
+ else
+ {
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SPKEY |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME;
+ }
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_full_key: ERR 0303: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ /* Check service key on context to see if match */
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "Comparing service key ...\n"
+ "return key is :\n");
+ for (i=0;i<=15;i++)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "service_key sent[%u]=%u , service_key returned[%u]=%u\n",
+ i,service_key[i],i,p_rec->service_key[i]);
+ }
+ /* since c15-0.1.14 not supported all key association queries should bring in return zero in service key */
+ if (cl_memcmp(skey,p_rec->service_key,16*sizeof(uint8_t)) != 0)
+ {
+ status = IB_REMOTE_ERROR;
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_full_key:"
+ "Data mismatch in service_key .\n"
+ );
+ goto Exit;
+ }
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_full_key: ERR 0364: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_full_key: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_register_service_with_data( IN osmtest_t * const p_osmt,
+ IN ib_net64_t service_id,
+ IN ib_net16_t service_pkey,
+ IN ib_net32_t service_lease,
+ IN uint8_t service_key_lsb,
+ IN uint8_t *service_data8,
+ IN ib_net16_t *service_data16,
+ IN ib_net32_t *service_data32,
+ IN ib_net64_t *service_data64,
+ IN char *service_name) {
+ osmv_query_req_t req;
+ osmv_user_query_t user;
+ osmtest_req_context_t context;
+ ib_service_record_t svc_rec,*p_rec;
+ osm_log_t *p_log = &p_osmt->log;
+ ib_api_status_t status;
+ /* ib_service_record_t* p_rec; */
+
+
+ OSM_LOG_ENTER( p_log, osmt_register_service_with_data );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service_with_data: "
+ "Registering Service: name:%s id:0x%" PRIx64 ".\n",
+ service_name, cl_ntoh64(service_id));
+
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+
+ /* set the new service record fields */
+ svc_rec.service_id = service_id;
+ svc_rec.service_pkey = service_pkey;
+ svc_rec.service_gid.unicast.prefix = 0;
+ svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+ svc_rec.service_lease = service_lease;
+ cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+ svc_rec.service_key[0] = service_key_lsb;
+
+ /* Copy data to service_data arrays */
+ cl_memcpy(svc_rec.service_data8,service_data8,16*sizeof(uint8_t));
+ cl_memcpy(svc_rec.service_data16,service_data16,8*sizeof(ib_net16_t));
+ cl_memcpy(svc_rec.service_data32,service_data32,4*sizeof(ib_net32_t));
+ cl_memcpy(svc_rec.service_data64,service_data64,2*sizeof(ib_net64_t));
+
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memcpy(svc_rec.service_name, service_name,
+ (strlen(service_name)+1)*sizeof(char));
+
+ /* prepare the data used for this query */
+ /* sa_mad_data.method = IB_MAD_METHOD_SET; */
+ /* sa_mad_data.sm_key = 0; */
+
+ context.p_osmt = p_osmt;
+ req.query_context = &context;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.sm_key = 0;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+ user.method = IB_MAD_METHOD_SET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ if (ib_pkey_is_invalid(service_pkey))
+ {
+ /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME |
+ IB_SR_COMPMASK_SDATA8_0 |
+ IB_SR_COMPMASK_SDATA8_1 |
+ IB_SR_COMPMASK_SDATA16_0 |
+ IB_SR_COMPMASK_SDATA16_1 |
+ IB_SR_COMPMASK_SDATA32_0 |
+ IB_SR_COMPMASK_SDATA32_1 |
+ IB_SR_COMPMASK_SDATA64_0 |
+ IB_SR_COMPMASK_SDATA64_1;
+ }
+ else
+ {
+ user.comp_mask = IB_SR_COMPMASK_SID |
+ IB_SR_COMPMASK_SGID |
+ IB_SR_COMPMASK_SPKEY |
+ IB_SR_COMPMASK_SLEASE |
+ IB_SR_COMPMASK_SKEY |
+ IB_SR_COMPMASK_SNAME|
+ IB_SR_COMPMASK_SDATA8_0 |
+ IB_SR_COMPMASK_SDATA8_1 |
+ IB_SR_COMPMASK_SDATA16_0 |
+ IB_SR_COMPMASK_SDATA16_1 |
+ IB_SR_COMPMASK_SDATA32_0 |
+ IB_SR_COMPMASK_SDATA32_1 |
+ IB_SR_COMPMASK_SDATA64_0 |
+ IB_SR_COMPMASK_SDATA64_1;
+ }
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ /* Dump to Service Data b4 send */
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_register_service_with_data:"
+ "Dumping service data b4 send\n");
+ osm_dump_service_record(&p_osmt->log,&svc_rec,OSM_LOG_VERBOSE);
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_data: ERR 0303: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_data: ERR 0364: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_data: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ /* Check data on context to see if match */
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "Comparing service data ...\n");
+ if (cl_memcmp(service_data8,p_rec->service_data8,16*sizeof(uint8_t)) != 0 ||
+ cl_memcmp(service_data16,p_rec->service_data16,8*sizeof(uint16_t)) != 0 ||
+ cl_memcmp(service_data32,p_rec->service_data32,4*sizeof(uint32_t)) != 0 ||
+ cl_memcmp(service_data64,p_rec->service_data64,2*sizeof(uint64_t)) != 0
+ )
+ {
+ status = IB_REMOTE_ERROR;
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_data: "
+ "Data mismatch in service_data8 ."
+ );
+ goto Exit;
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_get_service_by_id_and_name ( IN osmtest_t * const p_osmt,
+ IN uint32_t rec_num,
+ IN ib_net64_t sid,
+ IN char *sr_name,
+ OUT ib_service_record_t *p_out_rec
+ ) {
+
+ ib_api_status_t status = IB_SUCCESS;
+ osmtest_req_context_t context;
+ osmv_query_req_t req;
+ ib_service_record_t svc_rec,*p_rec;
+ uint32_t num_recs = 0;
+ osmv_user_query_t user;
+
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id_and_name: "
+ "Getting Service Record by id 0x%016" PRIx64 " and name : %s\n",
+ cl_ntoh64(sid),sr_name);
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ /* set the new service record fields */
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memcpy(svc_rec.service_name, sr_name,
+ (strlen(sr_name)+1)*sizeof(char));
+ svc_rec.service_id = sid;
+ /* prepare the data used for this query */
+ context.p_osmt = p_osmt;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ user.method = IB_MAD_METHOD_GET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SNAME;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: ERR 0365: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ num_recs = 0;
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: ERR 0370: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+ else
+ {
+ num_recs = context.result.result_cnt;
+ }
+
+ if ( num_recs != rec_num )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: "
+ "Unmatched record number , Expeceted : %d , Got : %d.\n",
+ rec_num , num_recs);
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id_and_name: "
+ "Found Service Record by Name:%s ID::0x%016" PRIx64 ".\n",
+ p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+ osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+ *p_out_rec = *p_rec;
+
+ Exit:
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id_and_name: "
+ "Expected num of records is : %d , Found number of records : %d\n",
+ rec_num,num_recs);
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_get_service_by_id ( IN osmtest_t * const p_osmt,
+ IN uint32_t rec_num,
+ IN ib_net64_t sid,
+ OUT ib_service_record_t *p_out_rec
+ ) {
+
+ ib_api_status_t status = IB_SUCCESS;
+ osmtest_req_context_t context;
+ osmv_query_req_t req;
+ ib_service_record_t svc_rec,*p_rec;
+ uint32_t num_recs = 0;
+ osmv_user_query_t user;
+
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id: "
+ "Getting Service Record by id 0x%016" PRIx64 "\n",
+ cl_ntoh64(sid));
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ /* set the new service record fields */
+ svc_rec.service_id = sid;
+ /* prepare the data used for this query */
+ context.p_osmt = p_osmt;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ user.method = IB_MAD_METHOD_GET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ user.comp_mask = IB_SR_COMPMASK_SID;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: ERR 0365: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ num_recs = 0;
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: ERR 0370: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+ else
+ {
+ num_recs = context.result.result_cnt;
+ }
+
+ if ( num_recs != rec_num )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: "
+ "Unmatched record number , Expeceted : %d , Got : %d.\n",
+ rec_num , num_recs);
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id: "
+ "Found Service Record by Name:%s ID::0x%016" PRIx64 ".\n",
+ p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+ osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+ *p_out_rec = *p_rec;
+
+ Exit:
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id: "
+ "Expected num of records is : %d , Found number of records : %d\n",
+ rec_num,num_recs);
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_get_service_by_name_and_key ( IN osmtest_t * const p_osmt,
+ IN char * sr_name,
+ IN uint32_t rec_num,
+ IN uint8_t *skey,
+ OUT ib_service_record_t *p_out_rec
+ ) {
+
+ ib_api_status_t status = IB_SUCCESS;
+ osmtest_req_context_t context;
+ osmv_query_req_t req;
+ ib_service_record_t svc_rec,*p_rec;
+ uint32_t num_recs = 0;
+ osmv_user_query_t user;
+
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name_and_key );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ uint8_t i;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name_and_key: "
+ "Getting Service Record by Name and Key :%s.\n",
+ sr_name);
+ for (i=0 ; i<=15 ; i++)
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "Service Key[%u] = %u\n",
+ i,skey[i]);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+ /* set the new service record fields */
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memcpy(svc_rec.service_name, sr_name,
+ (strlen(sr_name)+1)*sizeof(char));
+
+ /* prepare the data used for this query */
+ context.p_osmt = p_osmt;
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ user.method = IB_MAD_METHOD_GET;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ user.comp_mask = IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SKEY;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: ERR 0365: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ num_recs = 0;
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: ERR 0370: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+ else
+ {
+ num_recs = context.result.result_cnt;
+ }
+
+ if ( num_recs != rec_num )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: "
+ "Unmatched record number , Expeceted : %d , Got : %d.\n",
+ rec_num , num_recs);
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name_and_key: "
+ "Found Service Record by Name:%s ID::0x%016" PRIx64 ".\n",
+ sr_name, cl_ntoh64(p_rec->service_id));
+
+ osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+ *p_out_rec = *p_rec;
+
+ Exit:
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name_and_key: "
+ "Expected num of records is : %d , Found number of records : %d\n",
+ rec_num,num_recs);
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_get_service_by_name( IN osmtest_t * const p_osmt,
+ IN char * sr_name,
+ IN uint32_t rec_num,
+ OUT ib_service_record_t *p_out_rec
+ ) {
+
+ ib_api_status_t status = IB_SUCCESS;
+ osmtest_req_context_t context;
+ osmv_query_req_t req;
+ ib_service_record_t* p_rec;
+ ib_svc_name_t service_name;
+ uint32_t num_recs = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name: "
+ "Getting Service Record by Name:%s.\n",
+ sr_name);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+
+ context.p_osmt = p_osmt;
+
+ req.query_type = OSMV_QUERY_SVC_REC_BY_NAME;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ cl_memclr(service_name, sizeof(service_name));
+ cl_memcpy(service_name, sr_name, (strlen(sr_name)+1)*sizeof(char));
+ req.p_query_input = service_name;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: ERR 0365: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ /* The context struct is not init OR result with illegal number of records */
+ num_recs = 0;
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: ERR 0370: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+ else
+ {
+ num_recs = context.result.result_cnt;
+ }
+
+ if ( num_recs != rec_num )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: "
+ "Unmatched record number , Expeceted : %d , Got : %u.\n",
+ rec_num , num_recs);
+ status = IB_REMOTE_ERROR;
+ goto Exit;
+ }
+
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name: "
+ "Found Service Record by Name:%s ID::0x%016" PRIx64 ".\n",
+ sr_name, cl_ntoh64(p_rec->service_id));
+
+ osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+ *p_out_rec = *p_rec;
+
+ Exit:
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name: "
+ "Expected num of records is : %d , Found number of records : %u\n",
+ rec_num,num_recs);
+
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_get_all_services_and_check_names( IN osmtest_t * const p_osmt,
+ IN ib_svc_name_t * const p_valid_service_names_arr,
+ IN uint8_t num_of_valid_names,
+ OUT uint32_t *num_services) {
+ ib_api_status_t status = IB_SUCCESS;
+ osmtest_req_context_t context;
+ osmv_query_req_t req;
+ ib_service_record_t* p_rec;
+ uint32_t num_recs = 0,i,j;
+ uint8_t *p_checked_names;
+
+ OSM_LOG_ENTER(&p_osmt->log, osmt_get_all_services_and_check_names );
+ /* Prepare tracker for the checked names */
+ p_checked_names = (uint8_t*)cl_malloc(sizeof(uint8_t)*num_of_valid_names);
+ for (j=0 ; j<num_of_valid_names ; j++)
+ {
+ p_checked_names[j] = 0;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "Getting All Service Records\n");
+ }
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+
+ context.p_osmt = p_osmt;
+
+ req.query_type = OSMV_QUERY_ALL_SVC_RECS;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_all_services_and_check_names: ERR 0371: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_all_services_and_check_names: ERR 0372: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_all_services_and_check_names: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, i );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "Found Service Record by Name:%s ID::0x%016" PRIx64 ".\n",
+ p_rec->service_name, cl_ntoh64(p_rec->service_id));
+ osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE);
+ for ( j = 0; j < num_of_valid_names; j++)
+ {
+ /* If the service names exist in the record , mark it as checked (1) */
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "-I- Comparing source name : >%s< , with record name : >%s< , idx : %d\n",
+ p_valid_service_names_arr[j],p_rec->service_name , p_checked_names[j]);
+ if ( strcmp(p_valid_service_names_arr[j],p_rec->service_name) == 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "-I- The service %s is Valid\n",p_valid_service_names_arr[j]);
+ p_checked_names[j] = 1;
+ break;
+ }
+ }
+ }
+ /* Check that all service names have been identified */
+ for ( j = 0; j < num_of_valid_names; j++)
+ if (p_checked_names[j] == 0)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_all_services_and_check_names: ERR 0377: "
+ "Missing Valid Service Name:%s\n",p_valid_service_names_arr[j]);
+ status = IB_ERROR;
+ goto Exit;
+ }
+ *num_services = num_recs;
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+ib_api_status_t
+osmt_delete_service_by_name(IN osmtest_t * const p_osmt,
+ IN uint8_t IsServiceExist ,
+ IN char * sr_name , IN uint32_t rec_num) {
+ osmv_query_req_t req;
+ osmv_user_query_t user;
+ osmtest_req_context_t context;
+ ib_service_record_t svc_rec;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_delete_service_by_name);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_delete_service_by_name: "
+ "Trying to Delete Service: Name:%s.\n",
+ sr_name);
+
+ cl_memclr( &svc_rec, sizeof( svc_rec ) );
+
+ status = osmt_get_service_by_name(p_osmt, sr_name,rec_num, &svc_rec);
+ if (status != IB_SUCCESS)
+ {
+ if (IsServiceExist)
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_delete_service_by_name: ERR 001 "
+ "Nothing to delete - fail to find service by name: %s \n", sr_name);
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_delete_service_by_name: "
+ "Record Should not exist , i.e BAD flow\n");
+ status = IB_SUCCESS;
+ }
+ goto ExitNoDel;
+ }
+
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &user, sizeof( user ) );
+
+ /* set the new service record fields */
+ cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+ cl_memcpy(svc_rec.service_name, sr_name,
+ (strlen(sr_name)+1)*sizeof(char));
+
+ /* prepare the data used for this query */
+ context.p_osmt = p_osmt;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.query_context = &context;
+ req.query_type = OSMV_QUERY_USER_DEFINED; /* basicallya don't care here */
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.sm_key = 0;
+
+ user.method = IB_MAD_METHOD_DELETE;
+ user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ user.comp_mask = IB_SR_COMPMASK_SNAME;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_delete_service_by_name: ERR 0373: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_delete_service_by_name: ERR 0374: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_delete_service_by_name: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ ExitNoDel:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+/*
+ * Run a complete service records flow:
+ * - register a service
+ * - register a service (with a lease period)
+ * - get a service by name
+ * - get all services / must be 2
+ * - delete a service
+ * - get all services / must be 1
+ * - wait for the lease to expire
+ * - get all services / must be 0
+ * - get / set service by data
+ */
+ib_api_status_t
+osmt_run_service_records_flow( IN osmtest_t * const p_osmt ) {
+ ib_service_record_t srv_rec;
+ ib_api_status_t status;
+ uint8_t instance,i;
+ uint8_t service_data8[16],service_key[16];
+ ib_net16_t service_data16[8];
+ ib_net32_t service_data32[4];
+ ib_net64_t service_data64[2];
+ uint64_t pid = getpid();
+ uint64_t id[7];
+ /* We use up to seven service names - we use the extra for bad flow*/
+ ib_svc_name_t service_name[7];
+#ifdef VENDOR_RMPP_SUPPORT
+ /* This array contain only the valid names after registering vs SM */
+ ib_svc_name_t service_valid_names[3];
+ uint32_t num_recs = 0;
+#endif
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_run_service_records_flow);
+
+ /* Init Service names */
+ for (i=0 ; i<=6 ; i++ ) {
+ uint64_t rand1 = rand()-(uint64_t)i;
+ id[i] = abs((int)(pid - rand1));
+ /* Just to be unique any place on any host */
+ sprintf((char*)(service_name[i]),
+ "osmt.srvc.%" PRIu64 ".%" PRIu64 ,rand1,pid);
+ /*printf("-I- Service Name is : %s , ID is : 0x%" PRIx64 "\n",service_name[i],id[i]);*/
+ }
+ status = osmt_register_service(
+ p_osmt ,
+ cl_ntoh64(id[0]), /* IN ib_net64_t service_id, */
+ IB_DEFAULT_PKEY,/* IN ib_net16_t service_pkey, */
+ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */
+ 11, /* IN uint8_t service_key_lsb, */
+ (char*)service_name[0] /* IN char *service_name */
+ );
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_register_service(
+ p_osmt ,
+ cl_ntoh64(id[1]), /* IN ib_net64_t service_id, */
+ IB_DEFAULT_PKEY,/* IN ib_net16_t service_pkey, */
+ cl_hton32(0x00000001), /* IN ib_net32_t service_lease, */
+ 11, /* IN uint8_t service_key_lsb, */
+ (char*)service_name[1] /* IN char *service_name */
+ );
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_register_service(
+ p_osmt ,
+ cl_ntoh64(id[2]), /* IN ib_net64_t service_id, */
+ 0, /* IN ib_net16_t service_pkey, */
+ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */
+ 11, /* Remove Service Record IN uint8_t service_key_lsb, */
+ (char*)service_name[2] /* IN char *service_name */
+ );
+
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Generate 2 instances of service record with consecutive data */
+ for (instance = 0 ; instance < 2 ; instance++) {
+ /* First Clear all arrays */
+ cl_memclr (service_data8,16*sizeof(uint8_t));
+ cl_memclr (service_data16,8*sizeof(uint16_t));
+ cl_memclr (service_data32,4*sizeof(uint32_t));
+ cl_memclr (service_data64,2*sizeof(uint64_t));
+ service_data8[instance]=instance+1;
+ service_data16[instance]=cl_hton16(instance+2);
+ service_data32[instance]=cl_hton32(instance+3);
+ service_data64[instance]=cl_hton64(instance+4);
+ status = osmt_register_service_with_data(
+ p_osmt ,
+ cl_ntoh64(id[3]), /* IN ib_net64_t service_id, */
+ IB_DEFAULT_PKEY, /* IN ib_net16_t service_pkey, */
+ cl_ntoh32(10), /* IN ib_net32_t service_lease, */
+ 12, /* IN uint8_t service_key_lsb, */
+ service_data8,service_data16,service_data32,service_data64, /* service data structures */
+ (char*)service_name[3] /* IN char *service_name */
+ );
+
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ }
+
+ /* Trying to create service with zero key */
+ cl_memclr (service_key,16*sizeof(uint8_t));
+ status = osmt_register_service_with_full_key(
+ p_osmt ,
+ cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */
+ 0, /* IN ib_net16_t service_pkey, */
+ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */
+ service_key, /* full service_key , */
+ (char*)service_name[5] /* IN char *service_name */
+ );
+
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Now update it with Unique key and different service name */
+ for (i=0;i <= 15;i++) {
+ service_key[i]=i + 1;
+ }
+ status = osmt_register_service_with_full_key(
+ p_osmt ,
+ cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */
+ 0, /* IN ib_net16_t service_pkey, */
+ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */
+ service_key, /* full service_key , */
+ (char*)service_name[6] /* IN char *service_name */
+ );
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Let OpenSM handle it */
+ usleep(100);
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[0],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[1],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[2],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Try to get osmt.srvc.4 b4 (there should be 1 records ) and after 10 sec - It should be deleted */
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[3],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ sleep(10);
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[3],0, &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ /* Check that for the current Service ID only one record exists */
+ status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]),&srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Bad Flow of Get with invalid Service ID */
+ status = osmt_get_service_by_id(p_osmt, 0,cl_ntoh64(id[7]),&srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ /* Check that for correct name and ID we get record set b4 */
+ status = osmt_get_service_by_id_and_name(p_osmt , 1 , cl_ntoh64(id[0]),
+ (char*)service_name[0], &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ status = osmt_get_service_by_id_and_name(p_osmt , 1 , cl_ntoh64(id[5]),
+ (char*)service_name[6], &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Bad Flow of Get with valid name and invalid ID */
+ status = osmt_get_service_by_id_and_name(p_osmt , 0 , cl_ntoh64(id[0]),
+ (char*)service_name[3], &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ /* Bad Flow of Get with unmatched name (exists but not with the following ID) and valid ID */
+ status = osmt_get_service_by_id_and_name(p_osmt , 0 , cl_ntoh64(id[3]),
+ (char*)service_name[5], &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[4],0, &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ /* Bad Flow : Check that getting osmt.srvc.6 brings no records since another service has been updated with the same ID - osmt.srvc.7 */
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[5],0, &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ /* Check that getting osmt.srvc.7 by name ONLY is valid since we do not support key&name association , also trusted queries */
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[6],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Test Service Key */
+ cl_memclr(service_key,16*sizeof(uint8_t));
+ status = osmt_get_service_by_name_and_key (p_osmt ,
+ (char*)service_name[5],
+ 0, service_key,&srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ else
+ {
+ status = IB_SUCCESS;
+ }
+ status = osmt_get_service_by_name_and_key (p_osmt ,
+ (char*)service_name[6],
+ 0, service_key,&srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ else
+ {
+ status = IB_SUCCESS;
+ }
+
+ for (i=0;i <= 15;i++)
+ service_key[i]=i + 1;
+ status = osmt_get_service_by_name_and_key (p_osmt ,
+ (char*)service_name[6],
+ 0, service_key,&srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+ else
+ {
+ status = IB_SUCCESS;
+ }
+
+#ifdef VENDOR_RMPP_SUPPORT
+
+
+ cl_memcpy(&service_valid_names[0],&service_name[0],sizeof(uint8_t)*64);
+ cl_memcpy(&service_valid_names[1],&service_name[2],sizeof(uint8_t)*64);
+ cl_memcpy(&service_valid_names[2],&service_name[6],sizeof(uint8_t)*64);
+
+
+ status = osmt_get_all_services_and_check_names(p_osmt,service_valid_names,3, &num_recs);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+
+#endif
+ status = osmt_delete_service_by_name(p_osmt,1,
+ (char*)service_name[0],1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[0],1, &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: ERR 001 "
+ "Expected not to find osmt.srvc.1 \n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: "
+ "IS EXPECTED ERR ^^^^\n");
+
+ sleep(3);
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[1],1, &srv_rec);
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: ERR 001 "
+ "Expected not to find osmt.srvc.2 \n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: "
+ "IS EXPECTED ERR ^^^^\n");
+ status = IB_SUCCESS;
+ }
+
+ status = osmt_get_service_by_name(p_osmt,
+ (char*)service_name[2],1, &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: ERR 001 "
+ "Expected to find service osmt.srvc.3\n" );
+ goto Exit;
+ }
+ status = osmt_delete_service_by_name(p_osmt,1,
+ (char*)service_name[6],1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ /* Bad Flow */
+ status = osmt_delete_service_by_name(p_osmt,0,
+ (char*)service_name[5],1);
+ if (status == IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_delete_service_by_name(p_osmt,1,
+ (char*)service_name[2],1);
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/*
+ * Abstract:
+ * Implementation of SLtoVL and VL Arbitration testing flow..
+ * Top level is osmt_run_slvl_vlarbs_records_flow:
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+/* next error code: 16A */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_vl_arb_table( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_vl_arb_table_record_t * const p_rec )
+{
+ int result,i;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );
+
+ result = fprintf( fh,
+ "VL_ARBITRATION_TABLE\n"
+ "lid 0x%X\n"
+ "port_num 0x%X\n"
+ "block 0x%X\n",
+ cl_ntoh16( p_rec->lid ),
+ p_rec->port_num,
+ p_rec->block_num );
+
+ fprintf( fh, " ");
+ for (i = 0; i<32; i++) fprintf( fh,"| %-2u ", i);
+ fprintf( fh, "|\nVL: ");
+
+ for (i = 0; i<32; i++) fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].vl);
+ fprintf( fh, "|\nWEIGHT:");
+
+ for (i = 0; i<32; i++) fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].weight);
+ fprintf( fh,"|\nEND\n\n");
+
+ /* Exit: */
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
+ **********************************************************************/
+ib_api_status_t
+osmt_query_vl_arb(
+ IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN uint8_t const port_num,
+ IN uint8_t const block_num,
+ IN FILE *fh )
+{
+ osmtest_req_context_t context;
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_vl_arb_table_record_t record, *p_rec;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_query_vl_arb: "
+ "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X.\n",
+ cl_ntoh16( lid ) ,
+ port_num);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &context, sizeof( context ) );
+
+
+ context.p_osmt = p_osmt;
+
+ record.lid = lid;
+ record.port_num = port_num;
+ record.block_num = block_num;
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_vl_arb: ERR 0405: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_vl_arb: ERR 0466: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_vl_arb: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ /* ok it worked */
+ p_rec = osmv_get_query_result( context.result.p_result_madw, 0);
+ osmtest_write_vl_arb_table( p_osmt, fh, p_rec );
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+static ib_api_status_t
+osmt_query_all_ports_vl_arb( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ cl_status_t status = CL_SUCCESS;
+ cl_qmap_t *p_tbl;
+ port_t *p_src_port;
+ uint8_t block, anyErr = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_query_all_ports_vl_arb: "
+ "Obtaining ALL Ports VL Arbitration Tables.\n");
+
+ /*
+ * Go over all ports that exist in the subnet
+ * for each pair that are not switch ports get the path record
+ */
+
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+ p_src_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+ while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) ) {
+
+ /* HACK we use capability_mask to know diff a CA port from switch port */
+ if(p_src_port->rec.port_info.capability_mask )
+ {
+ /* this is an hca port */
+ for (block = 1; block <= 4; block++) {
+ /* NOTE to comply we must set port numbr to 0 and the SA should figure it out */
+ /* since it is a CA port */
+ status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, 0, block, fh);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_all_ports_vl_arb: ERR 0467: "
+ "Fail to get Lid:0x%X Port:0x%X (%s).\n",
+ cl_ntoh16(p_src_port->rec.lid), 0,
+ ib_get_err_str( status ) );
+ anyErr = 1;
+ }
+ }
+ }
+ else
+ {
+ /* this is a switch port */
+ for (block = 1; block <= 4; block++) {
+ status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid,
+ p_src_port->rec.port_num, block, fh);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_all_ports_vl_arb: ERR 0468: "
+ "Fail to get Lid:0x%X Port:0x%X (%s).\n",
+ cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num,
+ ib_get_err_str( status ) );
+ anyErr = 1;
+ }
+ }
+ }
+
+ p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item );
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ if (anyErr)
+ {
+ status = IB_ERROR;
+ }
+ return ( status );
+}
+
+/*******************************************************************************
+ SLtoVL
+*******************************************************************************/
+static ib_api_status_t
+osmtest_write_slvl_map_table( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_slvl_table_record_t * const p_rec )
+{
+ int result,i;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );
+
+ result = fprintf( fh,
+ "SLtoVL_MAP_TABLE\n"
+ "lid 0x%X\n"
+ "in_port_num 0x%X\n"
+ "out_port_num 0x%X\n",
+ cl_ntoh16( p_rec->lid ),
+ p_rec->in_port_num,
+ p_rec->out_port_num );
+
+ fprintf( fh, "SL:");
+ for (i = 0; i<16; i++) fprintf( fh,"| %-2u ", i);
+ fprintf( fh, "|\nVL:");
+
+ for (i = 0; i<16; i++) fprintf( fh,"| 0x%01X ",ib_slvl_table_get( &p_rec->slvl_tbl, i));
+ fprintf( fh,"|\nEND\n\n");
+
+ /* Exit: */
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
+ **********************************************************************/
+ib_api_status_t
+osmt_query_slvl_map(
+ IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN uint8_t const out_port_num,
+ IN uint8_t const in_port_num,
+ IN FILE *fh )
+{
+ osmtest_req_context_t context;
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_slvl_table_record_t record, *p_rec;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_query_slvl_map: "
+ "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X.\n",
+ cl_ntoh16( lid ) ,
+ out_port_num, in_port_num);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &context, sizeof( context ) );
+
+
+ context.p_osmt = p_osmt;
+
+ record.lid = lid;
+ record.in_port_num = in_port_num;
+ record.out_port_num = out_port_num;
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_slvl_map: ERR 0469: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_slvl_map: ERR 0470: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_slvl_map: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ /* ok it worked */
+ p_rec = osmv_get_query_result( context.result.p_result_madw, 0);
+ osmtest_write_slvl_map_table( p_osmt, fh, p_rec );
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+static ib_api_status_t
+osmt_query_all_ports_slvl_map( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ cl_status_t status = CL_SUCCESS;
+ cl_qmap_t *p_tbl;
+ port_t *p_src_port;
+ uint8_t in_port,anyErr = 0, num_ports;
+ node_t *p_node;
+ const cl_qmap_t *p_node_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_query_all_ports_slvl );
+
+ /*
+ * Go over all ports that exist in the subnet
+ * for each pair that are not switch ports get the relevant SLtoVLs
+ */
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_query_all_ports_slvl_map: "
+ "Obtaining ALL Ports (to other ports) SLtoVL Maps.\n");
+
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;
+ p_node_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+ p_src_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+ while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) ) {
+
+ /* HACK we use capability_mask to know diff a CA port from switch port */
+ if(p_src_port->rec.port_info.capability_mask )
+ {
+ /* this is an hca port */
+ /* NOTE to comply we must set port numbr to 0 and the SA should figure it out */
+ /* since it is a CA port */
+ status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0, 0, fh);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_all_ports_slvl_map: ERR 0471: "
+ "Fail to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s).\n",
+ cl_ntoh16(p_src_port->rec.lid), 0, 0,
+ ib_get_err_str( status ) );
+ anyErr = 1;
+ }
+ }
+ else
+ {
+ /* this is a switch port */
+ /* get the node */
+ p_node = ( node_t * ) cl_qmap_get( p_node_tbl, p_src_port->rec.lid );
+ if( p_node == ( node_t * ) cl_qmap_end( p_node_tbl ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_all_ports_slvl_map: ERR 0472: "
+ "Fail to get Node by Lid:0x%X\n",
+ p_src_port->rec.lid);
+ goto Exit;
+ }
+
+ num_ports = p_node->rec.node_info.num_ports;
+
+ for (in_port = 1; in_port <= num_ports; in_port++) {
+ status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid,
+ p_src_port->rec.port_num, in_port, fh);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_all_ports_slvl_map: ERR 0473: "
+ "Fail to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s).\n",
+ cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, in_port,
+ ib_get_err_str( status ) );
+ anyErr = 1;
+ }
+ }
+ }
+
+ p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ if (anyErr)
+ {
+ status = IB_ERROR;
+ }
+ return ( status );
+}
+
+/*
+ * Run a vl arbitration queries and sl2vl maps queries flow:
+ * Good flow:
+ * - for each physical port on the network - obtain the VL Arb
+ * - for each CA physical port obtain its SLtoVL Map
+ * - for each SW physical port (out) obtain the SLtoVL Map to each other port
+ * BAD flow:
+ * - Try get with multiple results
+ * - Try gettable
+ * - Try providing non existing port
+ */
+ib_api_status_t
+osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt ) {
+ ib_api_status_t status;
+ FILE *fh;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_run_vlarb_records_flow );
+
+ fh = fopen("vl_arbs.txt","w");
+ /* go over all ports in the subnet */
+
+ status = osmt_query_all_ports_vl_arb( p_osmt, fh );
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ status = osmt_query_all_ports_slvl_map( p_osmt, fh );
+ if (status != IB_SUCCESS)
+ {
+ goto Exit;
+ }
+
+ Exit:
+ fclose(fh);
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+#endif /* OSM_VENDOR_INTF_MTL */
+
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */
+
+/*
+ * Abstract:
+ * Implementation of osmtest_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+#ifdef __WIN__
+#pragma warning(disable : 4996)
+#endif
+
+/* next error code: 16A */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+#include <complib/cl_timer.h>
+
+
+#ifdef LINUX
+#define strnicmp strncasecmp
+#endif
+
+#define POOL_MIN_ITEMS 64
+#define GUID_ARRAY_SIZE 64
+
+typedef enum _osmtest_token_val
+ {
+ OSMTEST_TOKEN_COMMENT = 0,
+ OSMTEST_TOKEN_END,
+ OSMTEST_TOKEN_DEFINE_NODE,
+ OSMTEST_TOKEN_DEFINE_PORT,
+ OSMTEST_TOKEN_DEFINE_PATH,
+ OSMTEST_TOKEN_DEFINE_LINK,
+ OSMTEST_TOKEN_LID,
+ OSMTEST_TOKEN_BASE_VERSION,
+ OSMTEST_TOKEN_CLASS_VERSION,
+ OSMTEST_TOKEN_NODE_TYPE,
+ OSMTEST_TOKEN_NUM_PORTS,
+ OSMTEST_TOKEN_SYS_GUID,
+ OSMTEST_TOKEN_NODE_GUID,
+ OSMTEST_TOKEN_PORT_GUID,
+ OSMTEST_TOKEN_PARTITION_CAP,
+ OSMTEST_TOKEN_DEVICE_ID,
+ OSMTEST_TOKEN_REVISION,
+ OSMTEST_TOKEN_PORT_NUM,
+ OSMTEST_TOKEN_VENDOR_ID,
+ OSMTEST_TOKEN_DGID,
+ OSMTEST_TOKEN_SGID,
+ OSMTEST_TOKEN_DLID,
+ OSMTEST_TOKEN_SLID,
+ OSMTEST_TOKEN_HOP_FLOW_RAW,
+ OSMTEST_TOKEN_TCLASS,
+ OSMTEST_TOKEN_NUM_PATH,
+ OSMTEST_TOKEN_PKEY,
+ OSMTEST_TOKEN_SL,
+ OSMTEST_TOKEN_RATE,
+ OSMTEST_TOKEN_PKT_LIFE,
+ OSMTEST_TOKEN_PREFERENCE,
+ OSMTEST_TOKEN_MKEY,
+ OSMTEST_TOKEN_SUBN_PREF,
+ OSMTEST_TOKEN_BASE_LID,
+ OSMTEST_TOKEN_SM_BASE_LID,
+ OSMTEST_TOKEN_CAP_MASK,
+ OSMTEST_TOKEN_DIAG_CODE,
+ OSMTEST_TOKEN_MKEY_LEASE_PER,
+ OSMTEST_TOKEN_LOC_PORT_NUM,
+ OSMTEST_TOKEN_LINK_WID_EN,
+ OSMTEST_TOKEN_LINK_WID_SUP,
+ OSMTEST_TOKEN_LINK_WID_ACT,
+ OSMTEST_TOKEN_LINK_SPEED_SUP,
+ OSMTEST_TOKEN_PORT_STATE,
+ OSMTEST_TOKEN_STATE_INFO2,
+ OSMTEST_TOKEN_MKEY_PROT_BITS,
+ OSMTEST_TOKEN_LMC,
+ OSMTEST_TOKEN_LINK_SPEED,
+ OSMTEST_TOKEN_MTU_SMSL,
+ OSMTEST_TOKEN_VL_CAP,
+ OSMTEST_TOKEN_VL_HIGH_LIMIT,
+ OSMTEST_TOKEN_VL_ARB_HIGH_CAP,
+ OSMTEST_TOKEN_VL_ARB_LOW_CAP,
+ OSMTEST_TOKEN_MTU_CAP,
+ OSMTEST_TOKEN_VL_STALL_LIFE,
+ OSMTEST_TOKEN_VL_ENFORCE,
+ OSMTEST_TOKEN_MKEY_VIOL,
+ OSMTEST_TOKEN_PKEY_VIOL,
+ OSMTEST_TOKEN_QKEY_VIOL,
+ OSMTEST_TOKEN_GUID_CAP,
+ OSMTEST_TOKEN_SUBN_TIMEOUT,
+ OSMTEST_TOKEN_RESP_TIME_VAL,
+ OSMTEST_TOKEN_ERR_THRESHOLD,
+ OSMTEST_TOKEN_MTU,
+ OSMTEST_TOKEN_UNKNOWN
+ }
+osmtest_token_val_t;
+
+typedef struct _osmtest_token
+{
+ osmtest_token_val_t val;
+ size_t str_size;
+ const char *str;
+
+}
+osmtest_token_t;
+
+const osmtest_token_t token_array[] = {
+ {OSMTEST_TOKEN_COMMENT, 1, "#"},
+ {OSMTEST_TOKEN_END, 3, "END"},
+ {OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"},
+ {OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"},
+ {OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"},
+ {OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"},
+ {OSMTEST_TOKEN_LID, 3, "LID"},
+ {OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"},
+ {OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"},
+ {OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"},
+ {OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"},
+ {OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"},
+ {OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"},
+ {OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"},
+ {OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"},
+ {OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"},
+ {OSMTEST_TOKEN_REVISION, 8, "REVISION"},
+ {OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"},
+ {OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"},
+ {OSMTEST_TOKEN_DGID, 4, "DGID"},
+ {OSMTEST_TOKEN_SGID, 4, "SGID"},
+ {OSMTEST_TOKEN_DLID, 4, "DLID"},
+ {OSMTEST_TOKEN_SLID, 4, "SLID"},
+ {OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"},
+ {OSMTEST_TOKEN_TCLASS, 6, "TCLASS"},
+ {OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"},
+ {OSMTEST_TOKEN_PKEY, 4, "PKEY"},
+ {OSMTEST_TOKEN_SL, 2, "SL"},
+ {OSMTEST_TOKEN_RATE, 4, "RATE"},
+ {OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"},
+ {OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"},
+ {OSMTEST_TOKEN_MKEY, 4, "M_KEY"},
+ {OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"},
+ {OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"},
+ {OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"},
+ {OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"},
+ {OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"},
+ {OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"},
+ {OSMTEST_TOKEN_LOC_PORT_NUM, 14 , "local_port_num"},
+ {OSMTEST_TOKEN_LINK_WID_EN, 18 , "link_width_enabled"},
+ {OSMTEST_TOKEN_LINK_WID_SUP, 20 , "link_width_supported"},
+ {OSMTEST_TOKEN_LINK_WID_ACT, 17 , "link_width_active"},
+ {OSMTEST_TOKEN_LINK_SPEED_SUP, 20 , "link_speed_supported"},
+ {OSMTEST_TOKEN_PORT_STATE, 10 , "port_state"},
+ {OSMTEST_TOKEN_STATE_INFO2, 10 , "state_info2"},
+ {OSMTEST_TOKEN_MKEY_PROT_BITS, 3 , "mpb"},
+ {OSMTEST_TOKEN_LMC, 3 , "lmc"},
+ {OSMTEST_TOKEN_LINK_SPEED, 10 , "link_speed"},
+ {OSMTEST_TOKEN_MTU_SMSL, 8 , "mtu_smsl"},
+ {OSMTEST_TOKEN_VL_CAP, 6 , "vl_cap"},
+ {OSMTEST_TOKEN_VL_HIGH_LIMIT, 13 , "vl_high_limit"},
+ {OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"},
+ {OSMTEST_TOKEN_VL_ARB_LOW_CAP, 14, "vl_arb_low_cap"},
+ {OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"},
+ {OSMTEST_TOKEN_VL_STALL_LIFE, 13, "vl_stall_life"},
+ {OSMTEST_TOKEN_VL_ENFORCE, 10, "vl_enforce"},
+ {OSMTEST_TOKEN_MKEY_VIOL, 16, "m_key_violations"},
+ {OSMTEST_TOKEN_PKEY_VIOL, 16, "p_key_violations"},
+ {OSMTEST_TOKEN_QKEY_VIOL, 16, "q_key_violations"},
+ {OSMTEST_TOKEN_GUID_CAP, 8, "guid_cap"},
+ {OSMTEST_TOKEN_SUBN_TIMEOUT, 14, "subnet_timeout"},
+ {OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"},
+ {OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"},
+ {OSMTEST_TOKEN_MTU, 3, "MTU"}, /* must be after the other mtu... tokens. */
+ {OSMTEST_TOKEN_UNKNOWN, 0, ""} /* must be last entry */
+};
+
+#define IB_MAD_STATUS_CLASS_MASK (CL_HTON16(0xFF00))
+
+static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY";
+static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT";
+static const char ib_mad_status_str_unsup_class_ver[] =
+"IB_MAD_STATUS_UNSUP_CLASS_VER";
+static const char ib_mad_status_str_unsup_method[] =
+"IB_MAD_STATUS_UNSUP_METHOD";
+static const char ib_mad_status_str_unsup_method_attr[] =
+"IB_MAD_STATUS_UNSUP_METHOD_ATTR";
+static const char ib_mad_status_str_invalid_field[] =
+"IB_MAD_STATUS_INVALID_FIELD";
+static const char ib_mad_status_str_no_resources[] =
+"IB_SA_MAD_STATUS_NO_RESOURCES";
+static const char ib_mad_status_str_req_invalid[] =
+"IB_SA_MAD_STATUS_REQ_INVALID";
+static const char ib_mad_status_str_no_records[] =
+"IB_SA_MAD_STATUS_NO_RECORDS";
+static const char ib_mad_status_str_too_many_records[] =
+"IB_SA_MAD_STATUS_TOO_MANY_RECORDS";
+static const char ib_mad_status_str_invalid_gid[] =
+"IB_SA_MAD_STATUS_INVALID_GID";
+static const char ib_mad_status_str_insuf_comps[] =
+"IB_SA_MAD_STATUS_INSUF_COMPS";
+static const char generic_or_str[] = " | ";
+
+/**********************************************************************
+ **********************************************************************/
+const char *
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad )
+{
+ static char line[512];
+ uint32_t offset = 0;
+ ib_net16_t status;
+ boolean_t first = TRUE;
+
+ line[offset] = '\0';
+
+ status = ( ib_net16_t ) ( p_mad->status & IB_SMP_STATUS_MASK );
+
+ if( status == 0 )
+ {
+ strcat( &line[offset], "IB_SUCCESS" );
+ return ( line );
+ }
+
+ if( status & IB_MAD_STATUS_BUSY )
+ {
+ strcat( &line[offset], ib_mad_status_str_busy );
+ offset += sizeof( ib_mad_status_str_busy );
+ }
+ if( status & IB_MAD_STATUS_REDIRECT )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_redirect );
+ offset += sizeof( ib_mad_status_str_redirect ) - 1;
+ }
+ if( status & IB_MAD_STATUS_UNSUP_CLASS_VER )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_unsup_class_ver );
+ offset += sizeof( ib_mad_status_str_unsup_class_ver ) - 1;
+ }
+ if( status & IB_MAD_STATUS_UNSUP_METHOD )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_unsup_method );
+ offset += sizeof( ib_mad_status_str_unsup_method ) - 1;
+ }
+ if( status & IB_MAD_STATUS_UNSUP_METHOD_ATTR )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_unsup_method_attr );
+ offset += sizeof( ib_mad_status_str_unsup_method_attr ) - 1;
+ }
+ if( status & IB_MAD_STATUS_INVALID_FIELD )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_invalid_field );
+ offset += sizeof( ib_mad_status_str_invalid_field ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+ IB_SA_MAD_STATUS_NO_RESOURCES )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_no_resources );
+ offset += sizeof( ib_mad_status_str_no_resources ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+ IB_SA_MAD_STATUS_REQ_INVALID )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_req_invalid );
+ offset += sizeof( ib_mad_status_str_req_invalid ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) == IB_SA_MAD_STATUS_NO_RECORDS )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_no_records );
+ offset += sizeof( ib_mad_status_str_no_records ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_too_many_records );
+ offset += sizeof( ib_mad_status_str_too_many_records ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+ IB_SA_MAD_STATUS_INVALID_GID )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_invalid_gid );
+ offset += sizeof( ib_mad_status_str_invalid_gid ) - 1;
+ }
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+ IB_SA_MAD_STATUS_INSUF_COMPS )
+ {
+ if( !first )
+ {
+ strcat( &line[offset], generic_or_str );
+ offset += sizeof( generic_or_str ) - 1;
+ }
+ first = FALSE;
+ strcat( &line[offset], ib_mad_status_str_insuf_comps );
+ offset += sizeof( ib_mad_status_str_insuf_comps ) - 1;
+ }
+
+ return ( line );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+subnet_construct( IN subnet_t * const p_subn )
+{
+ cl_qmap_init( &p_subn->link_tbl );
+ cl_qmap_init( &p_subn->node_lid_tbl );
+ cl_qmap_init( &p_subn->node_guid_tbl );
+ /* NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */
+ /* cl_qmap_init( &p_subn->port_lid_tbl ); */
+ /* cl_qmap_init( &p_subn->port_guid_tbl ); */
+ /* port key is a lid and num pair */
+ cl_qmap_init( &p_subn->mgrp_mlid_tbl );
+ cl_qmap_init( &p_subn->port_key_tbl );
+ cl_qmap_init( &p_subn->path_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+subnet_init( IN subnet_t * const p_subn )
+{
+ cl_status_t status = IB_SUCCESS;
+
+ subnet_construct( p_subn );
+
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_construct( IN osmtest_t * const p_osmt )
+{
+ cl_memclr( p_osmt, sizeof( *p_osmt ) );
+ osm_log_construct( &p_osmt->log );
+ subnet_construct( &p_osmt->exp_subn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_destroy( IN osmtest_t * const p_osmt )
+{
+ cl_map_item_t *p_next_item,*p_item;
+
+ /* Currently there is a problem with IBAL exit flow - memory overrun , so we bypass the vendor deletion
+ Since it's already will be cleaned by the Windows OS . */
+#ifndef WIN32
+ if( p_osmt->p_vendor )
+ {
+ osm_vendor_delete( &p_osmt->p_vendor );
+ }
+#endif
+
+ cl_qpool_destroy( &p_osmt->port_pool );
+ cl_qpool_destroy( &p_osmt->node_pool );
+
+
+ /* destroy the qmap tables */
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.link_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.link_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_guid_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_guid_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_lid_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_lid_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.path_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.path_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.port_key_tbl );
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.port_key_tbl ) )
+ {
+ p_item = p_next_item;
+ p_next_item = cl_qmap_next( p_item );
+ cl_free( p_item );
+ }
+
+
+
+ osm_log_destroy( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_init( IN osmtest_t * const p_osmt,
+ IN const osmtest_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ )
+{
+ ib_api_status_t status;
+
+ /* Can't use log macros here, since we're initializing the log. */
+ osmtest_construct( p_osmt );
+
+ status = osm_log_init( &p_osmt->log, p_opt->force_log_flush,
+ 0x0001, p_opt->log_file );
+ if( status != IB_SUCCESS )
+ return ( status );
+ /* but we do not want any extra staff here */
+ osm_log_set_level( &p_osmt->log, log_flags );
+
+ osm_log( &p_osmt->log, OSM_LOG_FUNCS,
+ "osmtest_init: [\n" );
+
+ p_osmt->opt = *p_opt;
+
+ status = cl_qpool_init( &p_osmt->node_pool, POOL_MIN_ITEMS, 0,
+ POOL_MIN_ITEMS, sizeof( node_t ), NULL, NULL,
+ NULL );
+ CL_ASSERT( status == CL_SUCCESS );
+
+ status = cl_qpool_init( &p_osmt->port_pool, POOL_MIN_ITEMS, 0,
+ POOL_MIN_ITEMS, sizeof( port_t ), NULL, NULL,
+ NULL );
+ CL_ASSERT( status == CL_SUCCESS );
+
+ p_osmt->p_vendor = osm_vendor_new( &p_osmt->log,
+ p_opt->transaction_timeout );
+
+ if( p_osmt->p_vendor == NULL )
+ {
+ status = IB_INSUFFICIENT_RESOURCES;
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_init: ERR 0001: "
+ "Unable to allocate vendor object" );
+ goto Exit;
+ }
+
+ osm_mad_pool_construct( &p_osmt->mad_pool );
+ status = osm_mad_pool_init(
+ &p_osmt->mad_pool, &p_osmt->log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ osm_log( &p_osmt->log, OSM_LOG_FUNCS,
+ "osmtest_init: ]\n" );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec )
+{
+ osmtest_req_context_t *const p_ctxt =
+ ( osmtest_req_context_t * ) p_rec->query_context;
+ osmtest_t *const p_osmt = p_ctxt->p_osmt;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_query_res_cb );
+
+ p_ctxt->result = *p_rec;
+
+ if( p_rec->status != IB_SUCCESS )
+ {
+ if ( p_rec->status != IB_INVALID_PARAMETER )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_query_res_cb: ERR 0003: "
+ "Error on query (%s).\n", ib_get_err_str( p_rec->status ) );
+ }
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_all_recs( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const attr_id,
+ IN size_t const attr_size,
+ IN OUT osmtest_req_context_t * const p_context )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_all_recs );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_get_all_recs: "
+ "Getting all %s records.\n", ib_get_sa_attr_str( attr_id ) );
+ }
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+
+ p_context->p_osmt = p_osmt;
+ user.attr_id = attr_id;
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( attr_size >> 3 ) );
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_all_recs: ERR 0004: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_all_recs: ERR 0064: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_all_recs: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( p_context->result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_validate_sa_class_port_info( IN osmtest_t * const p_osmt)
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_query_req_t req;
+ ib_class_port_info_t *p_cpi;
+ osmtest_req_context_t context;
+ osmtest_req_context_t *p_context = &context;
+ ib_sa_mad_t *p_resp_sa_madp;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_sa_class_port_info );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_sa_class_port_info: "
+ "Getting Class Port Info\n");
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+
+ p_context->p_osmt = p_osmt;
+ req.query_type = OSMV_QUERY_CLASS_PORT_INFO;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = 0;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_sa_class_port_info: ERR 0065: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_sa_class_port_info: ERR 0070: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_sa_class_port_info: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( p_context->result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ /* ok we got it so please print it out */
+ p_resp_sa_madp = (ib_sa_mad_t*)osm_madw_get_mad_ptr(context.result.p_result_madw);
+ p_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr(p_resp_sa_madp );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmtest_validate_sa_class_port_info:\n-----------------------------\nSA Class Port Info:\n"
+ " base_ver:%u\n class_ver:%u\n cap_mask:0x%X\n resp_time_val:0x%X\n-----------------------------\n",
+ p_cpi->base_ver, p_cpi->class_ver, p_cpi->cap_mask, p_cpi->resp_time_val
+ );
+
+ Exit:
+ // if( context.result.p_result_madw != NULL )
+ //{
+ // osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ // context.result.p_result_madw = NULL;
+ //}
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_node_rec( IN osmtest_t * const p_osmt,
+ IN ib_net64_t const node_guid,
+ IN OUT osmtest_req_context_t * const p_context )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_node_record_t record;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_get_node_rec: "
+ "Getting node record for 0x%016" PRIx64 ".\n",
+ cl_ntoh64( node_guid ) );
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+
+ record.node_info.node_guid = node_guid;
+
+ p_context->p_osmt = p_osmt;
+ user.comp_mask = IB_NR_COMPMASK_NODEGUID;
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec: ERR 0071: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec: ERR 0072: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( p_context->result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ * Get a node record by node LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_node_rec_by_lid( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN OUT osmtest_req_context_t * const p_context )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_node_record_t record;
+ ib_mad_t *p_mad;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec_by_lid );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_get_node_rec_by_lid: "
+ "Getting node record for LID 0x%02X.\n",
+ cl_ntoh16( lid ) );
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+ record.lid = lid;
+
+ p_context->p_osmt = p_osmt;
+ user.comp_mask = IB_NR_COMPMASK_LID;
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec_by_lid: ERR 0073: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec_by_lid: ERR 0074: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+ if( status == IB_REMOTE_ERROR )
+ {
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_node_rec_by_lid: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( p_mad ));
+
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_guid_pair( IN osmtest_t * const p_osmt,
+ IN ib_net64_t sguid,
+ IN ib_net64_t dguid,
+ IN osmtest_req_context_t *p_context)
+{
+ cl_status_t status = IB_SUCCESS;
+ osmv_query_req_t req;
+ osmv_guid_pair_t guid_pair;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_guid_pair);
+
+ cl_memclr( p_context, sizeof( *p_context ) );
+
+ p_context->p_osmt = p_osmt;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+
+ req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+
+ guid_pair.dest_guid = dguid;
+ guid_pair.src_guid = sguid;
+
+ req.p_query_input = &guid_pair;
+ req.sm_key = 0;
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_get_path_rec_by_guid_pair: "
+ "Query for path from 0x%" PRIx64 " to 0x%" PRIx64"\n",
+ sguid,dguid );
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_guid_pair: ERR 0063: "
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = (*p_context).result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_guid_pair: ERR 0064: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_guid_pair: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( (*p_context).result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+
+ Exit:
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmtest_get_port_rec( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN OUT osmtest_req_context_t * const p_context )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_portinfo_record_t record;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_get_port_rec: "
+ "Getting PortRecord for port with LID 0x%X.\n",
+ cl_ntoh16( lid ) );
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+ record.lid = lid;
+
+ p_context->p_osmt = p_osmt;
+ user.comp_mask = IB_PIR_COMPMASK_LID;
+ user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec: ERR 0075: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec: ERR 0076: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( p_context->result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+ib_api_status_t
+osmtest_get_port_rec_by_num( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN uint8_t const port_num,
+ IN OUT osmtest_req_context_t * const p_context )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_portinfo_record_t record;
+ ib_mad_t *p_mad;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_get_port_rec_by_num: "
+ "Getting PortRecord for port with LID 0x%X Num:0x%X.\n",
+ cl_ntoh16( lid ) ,
+ port_num);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+ record.lid = lid;
+ record.port_num = port_num;
+ user.p_attr = &record;
+
+ p_context->p_osmt = p_osmt;
+
+ req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec_by_num: ERR 0077: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = p_context->result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ if (status != IB_INVALID_PARAMETER)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec_by_num: ERR 0078: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+ }
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_port_rec_by_num: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( p_mad ));
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );
+ }
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_large( IN osmtest_t * const p_osmt,
+ OUT uint32_t * const p_num_recs,
+ OUT uint32_t * const p_num_queries )
+{
+ osmtest_req_context_t context;
+ ib_portinfo_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ uint32_t num_recs = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_large );
+
+ cl_memclr( &context, sizeof( context ) );
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_stress_port_recs_large: ERR 0006: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Populate the database with the received records.
+ */
+ num_recs = context.result.result_cnt;
+ *p_num_recs += num_recs;
+ ++*p_num_queries;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_port_recs_large: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec =
+ osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+ osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_node_recs_large( IN osmtest_t * const p_osmt,
+ OUT uint32_t * const p_num_recs,
+ OUT uint32_t * const p_num_queries )
+{
+ osmtest_req_context_t context;
+ ib_node_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ uint32_t num_recs = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_node_recs_large );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_stress_node_recs_large: ERR 0007: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Populate the database with the received records.
+ */
+ num_recs = context.result.result_cnt;
+ *p_num_recs += num_recs;
+ ++*p_num_queries;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_node_recs_large: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+ osm_dump_node_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_path_recs_large( IN osmtest_t * const p_osmt,
+ OUT uint32_t * const p_num_recs,
+ OUT uint32_t * const p_num_queries )
+{
+ osmtest_req_context_t context;
+ ib_path_rec_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ uint32_t num_recs = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_large );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all Records in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+ sizeof( *p_rec ), &context );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_stress_path_recs_large: ERR 0008: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Populate the database with the received records.
+ */
+ num_recs = context.result.result_cnt;
+ *p_num_recs += num_recs;
+ ++*p_num_queries;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_path_recs_large: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+ osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+ib_api_status_t
+osmtest_stress_path_recs_by_guid ( IN osmtest_t * const p_osmt,
+ OUT uint32_t * const p_num_recs,
+ OUT uint32_t * const p_num_queries )
+{
+ osmtest_req_context_t context;
+ ib_path_rec_t *p_rec;
+ uint32_t i;
+ cl_status_t status = IB_SUCCESS;
+ uint32_t num_recs = 0;
+ node_t *p_src_node, *p_dst_node;
+ cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_by_guid );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ context.p_osmt = p_osmt;
+
+ p_tbl = &p_osmt->exp_subn.node_guid_tbl;
+
+ p_src_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ /*
+ * Go over all nodes that exist in the subnet
+ * for each pair that are not switch nodes get the path record
+ */
+ while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+ p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+ /*
+ * Do a blocking query for CA to CA Path Record
+ */
+ osm_log(&p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_path_recs_by_guid:"
+ "Source : guid = 0x%" PRIx64 " type = %d"
+ "Target : guid = 0x%" PRIx64 " type = %d\n",
+ cl_ntoh64(p_src_node->rec.node_info.port_guid),p_src_node->rec.node_info.node_type,
+ cl_ntoh64(p_dst_node->rec.node_info.port_guid),p_dst_node->rec.node_info.node_type);
+
+ if (p_src_node->rec.node_info.node_type == IB_NODE_TYPE_CA
+ && p_dst_node->rec.node_info.node_type == IB_NODE_TYPE_CA)
+ {
+ status = osmtest_get_path_rec_by_guid_pair(p_osmt ,
+ p_src_node->rec.node_info.port_guid,
+ p_dst_node->rec.node_info.port_guid,
+ &context);
+
+ /* In a case of TIMEOUT you still can try sending but cant count , maybe its a temporary issue */
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_stress_path_recs_by_guid: ERR 0008: "
+ "osmtest_get_path_rec_by_guid_pair failed (%s)\n",
+ ib_get_err_str( status ) );
+ if (status != IB_TIMEOUT)
+ goto Exit;
+ }
+ else
+ {
+ /* we might have received several records */
+ num_recs = context.result.result_cnt;
+ /*
+ * Populate the database with the received records.
+ */
+ *p_num_recs += num_recs;
+ ++*p_num_queries;
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_path_recs_by_guid: "
+ "Received %u records.\n", num_recs );
+ /* Dont waste time if not VERBOSE and above */
+ if (p_osmt->log.level & OSM_LOG_VERBOSE) {
+ for (i = 0; i < num_recs; i++) {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);
+ osm_dump_path_record(&p_osmt->log,p_rec,OSM_LOG_VERBOSE);
+ }
+ }
+ }
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+ }
+ /* next one please */
+ p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );
+ }
+ /* } */
+
+ p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );
+ }
+
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_small( IN osmtest_t * const p_osmt,
+ OUT uint32_t * const p_num_recs,
+ OUT uint32_t * const p_num_queries )
+{
+ osmtest_req_context_t context;
+ ib_portinfo_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ uint32_t num_recs = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_small );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for our own PortRecord in the subnet.
+ */
+ status = osmtest_get_port_rec( p_osmt,
+ cl_ntoh16(p_osmt->local_port.lid),
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_stress_port_recs_small: ERR 0009: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Populate the database with the received records.
+ */
+ num_recs = context.result.result_cnt;
+ *p_num_recs += num_recs;
+ ++*p_num_queries;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_stress_port_recs_small: "
+ "Received %u records.\n", num_recs );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec =
+ osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+ osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ * Use a wrong SM_Key in a simple port query and report success if
+ * failed.
+ **********************************************************************/
+ib_api_status_t
+osmtest_wrong_sm_key_ignored( IN osmtest_t * const p_osmt)
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_portinfo_record_t record;
+ osmtest_req_context_t context;
+ osmtest_req_context_t *p_context = &context;
+ uint8_t port_num = 1;
+
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_INFO ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmtest_wrong_sm_key_ignored: "
+ "Try PortRecord for port with LID 0x%X Num:0x%X.\n",
+ cl_ntoh16( p_osmt->local_port.sm_lid ) ,
+ port_num);
+ }
+
+ /*
+ * Do a blocking query for this record in the subnet.
+ * The result is returned in the result field of the caller's
+ * context structure.
+ *
+ * The query structures are locals.
+ */
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+ record.lid = p_osmt->local_port.sm_lid;
+ record.port_num = port_num;
+ user.p_attr = &record;
+
+ p_context->p_osmt = p_osmt;
+
+ req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 9999;
+ context.result.p_result_madw = NULL;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ /* since we use a wrong sm_key we should geta timeout */
+ if( status != IB_TIMEOUT )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_wrong_sm_key_ignored: ERR 0010: "
+ "Did not get a timeout but got (%s).\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+ else
+ {
+ status = IB_SUCCESS;
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_port_info( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_portinfo_record_t * const p_rec )
+{
+ int result;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );
+
+ result = fprintf( fh,
+ "DEFINE_PORT\n"
+ "lid 0x%X\n"
+ "port_num 0x%X\n"
+ "m_key 0x%016" PRIx64 "\n"
+ "subnet_prefix 0x%016" PRIx64 "\n"
+ "base_lid 0x%X\n"
+ "master_sm_base_lid 0x%X\n"
+ "capability_mask 0x%X\n"
+ "diag_code 0x%X\n"
+ "m_key_lease_period 0x%X\n"
+ "local_port_num 0x%X\n"
+ "link_width_enabled 0x%X\n"
+ "link_width_supported 0x%X\n"
+ "link_width_active 0x%X\n"
+ "link_speed_supported 0x%X\n"
+ "port_state %s\n"
+ "state_info2 0x%X\n"
+ "mpb 0x%X\n"
+ "lmc 0x%X\n"
+ "link_speed 0x%X\n"
+ "mtu_smsl 0x%X\n"
+ "vl_cap 0x%X\n"
+ "vl_high_limit 0x%X\n"
+ "vl_arb_high_cap 0x%X\n"
+ "vl_arb_low_cap 0x%X\n"
+ "mtu_cap 0x%X\n"
+ "vl_stall_life 0x%X\n"
+ "vl_enforce 0x%X\n"
+ "m_key_violations 0x%X\n"
+ "p_key_violations 0x%X\n"
+ "q_key_violations 0x%X\n"
+ "guid_cap 0x%X\n"
+ "subnet_timeout 0x%X\n"
+ "resp_time_value 0x%X\n"
+ "error_threshold 0x%X\n"
+ "END\n\n",
+ cl_ntoh16( p_rec->lid ),
+ p_rec->port_num,
+ cl_ntoh64( p_rec->port_info.m_key ),
+ cl_ntoh64( p_rec->port_info.subnet_prefix ),
+ cl_ntoh16( p_rec->port_info.base_lid ),
+ cl_ntoh16( p_rec->port_info.master_sm_base_lid ),
+ cl_ntoh32( p_rec->port_info.capability_mask ),
+ cl_ntoh16( p_rec->port_info.diag_code ),
+ cl_ntoh16( p_rec->port_info.m_key_lease_period ),
+ p_rec->port_info.local_port_num,
+ p_rec->port_info.link_width_enabled,
+ p_rec->port_info.link_width_supported,
+ p_rec->port_info.link_width_active,
+ ib_port_info_get_link_speed_sup( &p_rec->port_info ),
+ ib_get_port_state_str( ib_port_info_get_port_state
+ ( &p_rec->port_info ) ),
+ p_rec->port_info.state_info2,
+ ib_port_info_get_mpb( &p_rec->port_info ),
+ ib_port_info_get_lmc( &p_rec->port_info ),
+ p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl,
+ p_rec->port_info.vl_cap, p_rec->port_info.vl_high_limit,
+ p_rec->port_info.vl_arb_high_cap,
+ p_rec->port_info.vl_arb_low_cap,
+ p_rec->port_info.mtu_cap,
+ p_rec->port_info.vl_stall_life,
+ p_rec->port_info.vl_enforce,
+ cl_ntoh16( p_rec->port_info.m_key_violations ),
+ cl_ntoh16( p_rec->port_info.p_key_violations ),
+ cl_ntoh16( p_rec->port_info.q_key_violations ),
+ p_rec->port_info.guid_cap,
+ ib_port_info_get_timeout(&p_rec->port_info),
+ p_rec->port_info.resp_time_value,
+ p_rec->port_info.error_threshold );
+
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_port_info: ERR 001: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_path_info( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_path_rec_t * const p_rec )
+{
+ int result;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_path_info );
+
+ result = fprintf( fh,
+ "DEFINE_PATH\n"
+ "dgid 0x%016" PRIx64 " 0x%016" PRIx64
+ "\nsgid 0x%016" PRIx64 " 0x%016" PRIx64
+ "\ndlid 0x%X\n"
+ "slid 0x%X\n"
+ "# hop_flow_raw 0x%X\n"
+ "# tclass 0x%X\n"
+ "# num_path 0x%X\n"
+ "pkey 0x%X\n"
+ "# sl 0x%X\n"
+ "# mtu 0x%X\n"
+ "# rate 0x%X\n"
+ "# pkt_life 0x%X\n"
+ "# preference 0x%X\n" "END\n\n",
+ cl_ntoh64( p_rec->dgid.unicast.prefix ),
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ),
+ cl_ntoh64( p_rec->sgid.unicast.prefix ),
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ),
+ cl_ntoh16( p_rec->dlid ), cl_ntoh16( p_rec->slid ),
+ cl_ntoh32( p_rec->hop_flow_raw ), p_rec->tclass,
+ p_rec->num_path, cl_ntoh16( p_rec->pkey ), p_rec->sl,
+ p_rec->mtu, p_rec->rate, p_rec->pkt_life,
+ p_rec->preference );
+
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_path_info: ERR 002: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_node_info( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_node_record_t * const p_rec )
+{
+ int result;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_node_info );
+
+ result = fprintf( fh,
+ "DEFINE_NODE\n"
+ "lid 0x%X\n"
+ "base_version 0x%X\n"
+ "class_version 0x%X\n"
+ "node_type 0x%X # (%s)\n"
+ "num_ports 0x%X\n"
+ "sys_guid 0x%016" PRIx64 "\n"
+ "node_guid 0x%016" PRIx64 "\n"
+ "port_guid 0x%016" PRIx64 "\n"
+ "partition_cap 0x%X\n"
+ "device_id 0x%X\n"
+ "revision 0x%X\n"
+ "# port_num 0x%X\n"
+ "# vendor_id 0x%X\n"
+ "# node_desc %s\n"
+ "END\n\n",
+ cl_ntoh16( p_rec->lid ),
+ p_rec->node_info.base_version,
+ p_rec->node_info.class_version,
+ p_rec->node_info.node_type,
+ ib_get_node_type_str( p_rec->node_info.node_type ),
+ p_rec->node_info.num_ports,
+ cl_ntoh64( p_rec->node_info.sys_guid ),
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh64( p_rec->node_info.port_guid ),
+ cl_ntoh16( p_rec->node_info.partition_cap ),
+ cl_ntoh16( p_rec->node_info.device_id ),
+ cl_ntoh32( p_rec->node_info.revision ),
+ ib_node_info_get_local_port_num( &p_rec->node_info ),
+ cl_ntoh32( ib_node_info_get_vendor_id
+ ( &p_rec->node_info ) ),
+ p_rec->node_desc.description );
+
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_node_info: ERR 003: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#if 0
+
+/* HACK: we do not support link records for now. */
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_link( IN osmtest_t * const p_osmt,
+ IN FILE * fh,
+ IN const ib_link_record_t * const p_rec )
+{
+ int result;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_link );
+
+ result = fprintf( fh,
+ "DEFINE_LINK\n"
+ "from_lid 0x%X\n"
+ "from_port_num 0x%X\n"
+ "to_port_num 0x%X\n"
+ "to_lid 0x%X\n"
+ "END\n\n",
+ cl_ntoh16( p_rec->from_lid ),
+ p_rec->from_port_num,
+ p_rec->to_port_num, cl_ntoh16( p_rec->to_lid ) );
+
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_link: ERR 004: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_link_recs( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_link_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+ int result;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_link_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_LINK_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_link_recs: ERR 005: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Write the received records out to the file.
+ */
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_write_all_link_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ result = fprintf( fh, "#\n" "# Link Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_link_recs: ERR 006: "
+ "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec =
+ ( ib_link_record_t * ) osmv_get_query_result( context.result.
+ p_result_madw, i );
+
+ osmtest_write_link( p_osmt, fh, p_rec );
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_lid_pair( IN osmtest_t * const p_osmt,
+ IN ib_net16_t slid,
+ IN ib_net16_t dlid,
+ IN osmtest_req_context_t *p_context)
+{
+ cl_status_t status = IB_SUCCESS;
+ osmv_query_req_t req;
+ osmv_lid_pair_t lid_pair;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_lid_pair);
+
+ cl_memclr( p_context, sizeof( *p_context ) );
+
+ p_context->p_osmt = p_osmt;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = p_context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+
+ req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;
+
+ lid_pair.dest_lid = dlid;
+ lid_pair.src_lid = slid;
+
+ req.p_query_input = &lid_pair;
+ req.sm_key = 0;
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_get_path_rec_by_lid_pair: "
+ "Query for path from 0x%X to 0x%X\n",
+ slid,dlid );
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_lid_pair: ERR 0053: "
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = (*p_context).result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_lid_pair: ERR 0067: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_get_path_rec_by_lid_pair: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( (*p_context).result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+
+ Exit:
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ASSUMES RMPP IMPL
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_node_recs( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_node_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+ int result;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_node_recs: ERR 0022: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Write the received records out to the file.
+ */
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_write_all_node_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_node_recs: ERR 0023: "
+ "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+ osmtest_write_node_info( p_osmt, fh, p_rec );
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ * ASSUMES RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_portinfo_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+ int result;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_port_recs: ERR 007: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Write the received records out to the file.
+ */
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_write_all_port_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_port_recs: ERR 0024: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+ osmtest_write_port_info( p_osmt, fh, p_rec );
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ASSUMES RMPP IMPL
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs(
+ IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_path_rec_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+ int result;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all records in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_path_recs: ERR 0025: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Write the received records out to the file.
+ */
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_write_all_path_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ result = fprintf( fh, "#\n" "# Path Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_path_recs: ERR 0026: "
+ "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+ osmtest_write_path_info( p_osmt, fh, p_rec );
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#else
+
+/*
+ * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER:
+ */
+static ib_api_status_t
+osmtest_write_all_node_recs(
+ IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ node_t *p_node;
+ node_t *p_guid_node;
+ const ib_node_record_t *p_rec;
+ cl_status_t status = CL_SUCCESS;
+ int result;
+ uint16_t lid;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );
+
+ result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_node_recs: ERR 0027: "
+ "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Go over all LIDS in the range 1 to max_lid and do a
+ * NodeRecord query by that lid.
+ */
+ for (lid = 1; lid <= p_osmt->max_lid; lid++) {
+ /* prepare the qury context */
+ cl_memclr( &context, sizeof( context ) );
+
+ status = osmtest_get_node_rec_by_lid( p_osmt, cl_ntoh16( lid ), &context );
+ if( status != IB_SUCCESS )
+ {
+ if ( (status != IB_INVALID_PARAMETER) && (status != IB_SA_MAD_STATUS_NO_RECORDS))
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_write_all_node_recs: ERR 0028: "
+ "failed to get node info for LID:0x%02X.(%s)\n",
+ cl_ntoh16( lid ),
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_write_all_node_recs: WRN 0121: "
+ "failed to get node info for LID:0x%02X.(%s)\n",
+ cl_ntoh16( lid ),
+ ib_get_err_str( status ) );
+ status = IB_SUCCESS;
+ }
+ }
+ else
+ {
+ /* OK we got something */
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, 0);
+ osmtest_write_node_info( p_osmt, fh, p_rec );
+
+ /* create a subnet object */
+ p_node = node_new( );
+ CL_ASSERT( p_node != NULL );
+
+ /* copy the info to the subnet node object */
+ p_node->rec = *p_rec;
+
+ cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,
+ p_node->rec.lid, &p_node->map_item );
+
+ p_guid_node = node_new( );
+ CL_ASSERT( p_guid_node != NULL );
+
+ *p_guid_node = *p_node;
+
+ cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,
+ p_guid_node->rec.node_info.node_guid,
+ &p_guid_node->map_item );
+
+ }
+
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+ }
+
+ Exit:
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/*
+ * GET ALL PORT RECORDS IN THE FABRIC -
+ * one by one by using the node info received
+ */
+
+static ib_api_status_t
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_node_record_t *p_node_rec;
+ const ib_portinfo_record_t *p_rec;
+ uint8_t port_num;
+ cl_status_t status = CL_SUCCESS;
+ cl_qmap_t *p_tbl;
+ node_t *p_node;
+ port_t *p_port;
+ int result;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /* print header */
+ result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );
+ if( result < 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_port_recs: ERR 0029: " "Write failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* use the pre-explored set of nodes */
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+ p_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ /*
+ * Go over all LIDS in the range 1 to max_lid and do a
+ * NodeRecord query by that lid.
+ */
+ while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )
+ {
+
+ p_node_rec = &(p_node->rec);
+
+ /* go through all ports of the node: */
+ for (port_num = 0; port_num <= p_node_rec->node_info.num_ports; port_num++) {
+ /* prepare the qury context */
+ cl_memclr( &context, sizeof( context ) );
+
+ status = osmtest_get_port_rec_by_num( p_osmt,
+ p_node_rec->lid,
+ port_num,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ if( (status != IB_INVALID_PARAMETER) && (status != IB_SA_MAD_STATUS_NO_RECORDS))
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_write_all_port_recs: WRN 0121: "
+ "Error encountered getting port info for LID:0x%04X Num:0x%02X.(%s)\n",
+ p_node_rec->lid, port_num,
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_write_all_port_recs: WRN 0121: "
+ "failed to get port info for LID:0x%04X Num:0x%02X.(%s)\n",
+ p_node_rec->lid, port_num,
+ ib_get_err_str( status ) );
+ status = IB_SUCCESS;
+ }
+ }
+ else
+ {
+ /* OK we got something */
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);
+ osmtest_write_port_info( p_osmt, fh, p_rec );
+
+ /* create a subnet object */
+ p_port = port_new( );
+ CL_ASSERT( p_port != NULL );
+
+ /* copy the info to the subnet node object */
+ p_port->rec = *p_rec;
+
+ cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,
+ port_gen_id(p_node_rec->lid, port_num), &p_port->map_item );
+ }
+
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+ }
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+ }
+
+ /* we must set the exist status to avoid abort of the over all algorith */
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ASSUMES NO RMPP
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs( IN osmtest_t * const p_osmt,
+ IN FILE * fh )
+{
+ osmtest_req_context_t context;
+ const ib_path_rec_t *p_rec;
+ cl_status_t status = CL_SUCCESS;
+ int num_recs, i;
+ cl_qmap_t *p_tbl;
+ node_t *p_src_node, *p_dst_node;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Go over all nodes that exist in the subnet
+ * for each pair that are not switch nodes get the path record
+ */
+
+ context.p_osmt = p_osmt;
+
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+ p_src_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+ /* HACK we use capability_mask to know diff a CA node from switch node */
+ /* if(p_src_node->rec.node_info.capability_mask ) { */
+ p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+ /* HACK we use capability_mask to know diff a CA node from switch node */
+ /* if (p_dst_node->rec.node_info.capability_mask) { */
+
+ /* query for it: */
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt,
+ p_src_node->rec.lid,
+ p_dst_node->rec.lid,
+ &context);
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_write_all_path_recs: WRN 0121: "
+ "failed to get path info from LID:0x%X To LID:0x%X.(%s)\n",
+ p_src_node->rec.lid, p_dst_node->rec.lid,
+ ib_get_err_str( status ) );
+ }
+ else
+ {
+ /* we might have received several records */
+ num_recs = context.result.result_cnt;
+ for (i = 0; i < num_recs; i++) {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);
+ osmtest_write_path_info( p_osmt, fh, p_rec );
+ }
+ }
+ /* } */
+
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ /* next one please */
+ p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );
+ }
+ /* } */
+
+ p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );
+ }
+
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_create_inventory_file( IN osmtest_t * const p_osmt )
+{
+ FILE *fh;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_create_inventory_file );
+
+ fh = fopen( p_osmt->opt.file_name, "w" );
+ if( fh == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_create_inventory_file: ERR 0079: "
+ "Unable to open inventory file (%s).\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* HACK: the order is important: nodes ports paths */
+ status = osmtest_write_all_node_recs( p_osmt, fh );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osmtest_write_all_port_recs( p_osmt, fh );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ if (! p_osmt->opt.ignore_path_records)
+ {
+ status = osmtest_write_all_path_recs( p_osmt, fh );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ }
+
+ /*
+ status = osmtest_write_all_link_recs( p_osmt, fh );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ */
+ fclose( fh );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_stress_large_rmpp_pr( IN osmtest_t * const p_osmt )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint64_t num_recs = 0;
+ uint64_t num_queries = 0;
+ uint32_t delta_recs;
+ uint32_t delta_queries;
+ uint32_t print_freq = 0;
+ struct timeval start_tv,end_tv;
+ long sec_diff,usec_diff;
+ float ratio;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp_pr );
+ gettimeofday( &start_tv, NULL );
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+
+ while( num_queries < STRESS_LARGE_PR_RMPP_THR )
+ {
+ delta_recs = 0;
+ delta_queries = 0;
+
+ status = osmtest_stress_path_recs_by_guid( p_osmt, &delta_recs,
+ &delta_queries );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ num_recs += delta_recs;
+ num_queries += delta_queries;
+
+ print_freq += delta_recs;
+ if( print_freq > 10000 )
+ {
+ gettimeofday( &end_tv, NULL );
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ printf("-I- Quering %" PRId64 " Path Record queries CA to CA (rmpp) \n\ttook %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+ if (num_recs == 0)
+ ratio = 0;
+ else
+ ratio = (float) (num_queries / num_recs);
+ printf( "-I- Queries to Record Ratio is %" PRIu64 " records, %" PRIu64 " queries : %.2f \n",
+ num_recs, num_queries, ratio);
+ print_freq = 0;
+ }
+ }
+
+ Exit:
+ gettimeofday( &end_tv, NULL );
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+
+ printf("-I- Quering %" PRId64 " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+static ib_api_status_t
+osmtest_stress_large_rmpp( IN osmtest_t * const p_osmt )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint64_t num_recs = 0;
+ uint64_t num_queries = 0;
+ uint32_t delta_recs;
+ uint32_t delta_queries;
+ uint32_t print_freq = 0;
+ struct timeval start_tv,end_tv;
+ struct timezone tz;
+ long sec_diff,usec_diff;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp );
+ gettimeofday( &start_tv, &tz );
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+
+ while( num_queries < STRESS_LARGE_RMPP_THR )
+ {
+ delta_recs = 0;
+ delta_queries = 0;
+
+ status = osmtest_stress_node_recs_large( p_osmt, &delta_recs,
+ &delta_queries );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osmtest_stress_path_recs_large( p_osmt, &delta_recs,
+ &delta_queries );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osmtest_stress_port_recs_large( p_osmt, &delta_recs,
+ &delta_queries );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ num_recs += delta_recs;
+ num_queries += delta_queries;
+
+ print_freq += delta_recs;
+
+ if( print_freq > 100000 )
+ {
+ gettimeofday( &end_tv, &tz );
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ printf("-I- Quering %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+ printf( "%" PRIu64 " records, %" PRIu64 " queries\n",
+ num_recs, num_queries );
+ print_freq = 0;
+ }
+ }
+
+ Exit:
+ gettimeofday( &end_tv, &tz );
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+
+ printf("-I- Quering %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_stress_small_rmpp( IN osmtest_t * const p_osmt )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint64_t num_recs = 0;
+ uint64_t num_queries = 0;
+ uint32_t delta_recs;
+ uint32_t delta_queries;
+ uint32_t print_freq = 0;
+ int num_timeouts = 0;
+ struct timeval start_tv,end_tv;
+ struct timezone tz;
+ long sec_diff,usec_diff;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_small_rmpp );
+ gettimeofday( &start_tv, &tz );
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+ while( (num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100) )
+ {
+ delta_recs = 0;
+ delta_queries = 0;
+
+ status = osmtest_stress_port_recs_small( p_osmt, &delta_recs,
+ &delta_queries );
+
+ num_recs += delta_recs;
+ num_queries += delta_queries;
+
+ print_freq += delta_recs;
+ if( print_freq > 5000 )
+ {
+ gettimeofday( &end_tv, &tz );
+ printf( "%" PRIu64 " records, %" PRIu64 " queries\n",
+ num_recs, num_queries );
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ printf("-I- Quering %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+ print_freq = 0;
+ }
+ }
+ gettimeofday( &end_tv, &tz );
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+ end_tv.tv_sec, (long)end_tv.tv_usec);
+ if (end_tv.tv_usec > start_tv.tv_usec) {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+ } else {
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+ }
+
+ printf("-I- Quering %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",num_queries,
+ sec_diff,usec_diff);
+ if (num_timeouts > 50)
+ {
+ status = IB_TIMEOUT;
+ }
+ /* Exit: */
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osmtest_prepare_db_generic( IN osmtest_t * const p_osmt,
+ IN cl_qmap_t * const p_tbl )
+{
+ generic_t *p_generic;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db_generic );
+
+ p_generic = ( generic_t * ) cl_qmap_head( p_tbl );
+
+ while( p_generic != ( generic_t * ) cl_qmap_end( p_tbl ) )
+ {
+ p_generic->count = 0;
+ p_generic = ( generic_t * ) cl_qmap_next( &p_generic->map_item );
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osmtest_prepare_db( IN osmtest_t * const p_osmt )
+{
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db );
+
+ osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.node_lid_tbl );
+ osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.path_tbl );
+
+ OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_nodes( IN osmtest_t * const p_osmt )
+{
+ const node_t *p_node;
+ cl_status_t status = IB_SUCCESS;
+ cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_nodes );
+
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+ p_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+ while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )
+ {
+ if( p_node->count == 0 )
+ {
+ /*
+ * This node was not reported by the SA
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_check_missing_nodes: ERR 0080: "
+ "Missing node 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );
+ status = IB_ERROR;
+ }
+
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_ports( IN osmtest_t * const p_osmt )
+{
+ const port_t *p_port;
+ cl_status_t status = IB_SUCCESS;
+ cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_ports );
+
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+ p_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+ while( p_port != ( port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ if( p_port->count == 0 )
+ {
+ /*
+ * This port was not reported by the SA
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_check_missing_ports: ERR 0081: "
+ "Missing port LID:0x%X Num:0x%X.\n",
+ cl_ntoh16( p_port->rec.lid), p_port->rec.port_num);
+ status = IB_ERROR;
+ }
+
+ p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_paths( IN osmtest_t * const p_osmt )
+{
+ const path_t *p_path;
+ cl_status_t status = IB_SUCCESS;
+ cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_paths );
+
+ p_tbl = &p_osmt->exp_subn.path_tbl;
+
+ p_path = ( path_t * ) cl_qmap_head( p_tbl );
+
+ while( p_path != ( path_t * ) cl_qmap_end( p_tbl ) )
+ {
+ if( p_path->count == 0 )
+ {
+ /*
+ * This path was not reported by the SA
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_check_missing_paths: ERR 0051: "
+ "SA did not return path SLID 0x%X to DLID 0x%X.\n",
+ cl_ntoh16( p_path->rec.slid ),
+ cl_ntoh16( p_path->rec.dlid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+inline uint32_t
+osmtest_path_rec_key_get( IN const ib_path_rec_t * const p_rec )
+{
+ return ( p_rec->dlid << 16 | p_rec->slid );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+osmtest_path_rec_kay_is_valid( IN osmtest_t * const p_osmt,
+ IN const path_t * const p_path )
+{
+ if( ( p_path->comp.dlid == 0 ) || ( p_path->comp.slid == 0 ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_path_rec_kay_is_valid: ERR 008: "
+ "SLID and DLID must be specified for defined paths.\n" );
+ return ( FALSE );
+ }
+
+ return ( TRUE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_data( IN osmtest_t * const p_osmt,
+ IN path_t * const p_path,
+ IN const ib_path_rec_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_data );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_data: "
+ "Checking path SLID 0x%X to DLID 0x%X.\n",
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+ }
+
+
+ /*
+ * Has this record already been returned?
+ */
+ if( p_path->count != 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_data: ERR 0056: "
+ "Already received path SLID 0x%X to DLID 0x%X.\n",
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++p_path->count;
+
+ /*
+ * Check the fields the user wants checked.
+ */
+ if( ( p_path->comp.dgid.unicast.interface_id &
+ p_path->rec.dgid.unicast.interface_id ) !=
+ ( p_path->comp.dgid.unicast.interface_id &
+ p_rec->dgid.unicast.interface_id ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_data: ERR 009: "
+ "DGID mismatch on path SLID 0x%X to DLID 0x%X.\n"
+ "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"
+ "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+ cl_ntoh16( p_path->rec.slid ),
+ cl_ntoh16( p_path->rec.dlid ),
+ cl_ntoh64( p_path->rec.dgid.unicast.prefix ),
+ cl_ntoh64( p_path->rec.dgid.unicast.interface_id ),
+ cl_ntoh64( p_rec->dgid.unicast.prefix ),
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Check the fields the user wants checked.
+ */
+ if( ( p_path->comp.sgid.unicast.interface_id &
+ p_path->rec.sgid.unicast.interface_id ) !=
+ ( p_path->comp.sgid.unicast.interface_id &
+ p_rec->sgid.unicast.interface_id ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_data: ERR 0011: "
+ "SGID mismatch on path SLID 0x%X to DLID 0x%X.\n"
+ "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"
+ "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+ cl_ntoh16( p_path->rec.slid ),
+ cl_ntoh16( p_path->rec.dlid ),
+ cl_ntoh64( p_path->rec.sgid.unicast.prefix ),
+ cl_ntoh64( p_path->rec.sgid.unicast.interface_id ),
+ cl_ntoh64( p_rec->sgid.unicast.prefix ),
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Compare the fields the user wishes to validate.
+ */
+ if( ( p_path->comp.pkey & p_path->rec.pkey ) !=
+ ( p_path->comp.pkey & p_rec->pkey ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_data: ERR 0012: "
+ "PKEY mismatch on path SLID 0x%X to DLID 0x%X.\n"
+ "\t\t\t\tExpected 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_path->rec.slid ),
+ cl_ntoh16( p_path->rec.dlid ),
+ cl_ntoh64( p_path->rec.pkey ), cl_ntoh64( p_rec->pkey ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_data( IN osmtest_t * const p_osmt,
+ IN node_t * const p_node,
+ IN const ib_node_record_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_data );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: "
+ "Checking node 0x%016" PRIx64 ", LID 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ) );
+ }
+
+ /*
+ * Has this record already been returned?
+ */
+ if( p_node->count != 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0013: "
+ "Already received node 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++p_node->count;
+
+ /*
+ * Compare the fields the user wishes to validate.
+ */
+ if( ( p_node->comp.lid & p_node->rec.lid ) !=
+ ( p_node->comp.lid & p_rec->lid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0014: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected LID 0x%X, received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ), p_node->rec.lid, p_rec->lid );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.base_version &
+ p_node->rec.node_info.base_version ) !=
+ ( p_node->comp.node_info.base_version &
+ p_rec->node_info.base_version ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0015: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected base_version 0x%X, received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ p_node->rec.node_info.base_version,
+ p_rec->node_info.base_version );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.class_version &
+ p_node->rec.node_info.class_version ) !=
+ ( p_node->comp.node_info.class_version &
+ p_rec->node_info.class_version ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0016: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected class_version 0x%X, received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ p_node->rec.node_info.class_version,
+ p_rec->node_info.class_version );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.node_type &
+ p_node->rec.node_info.node_type ) !=
+ ( p_node->comp.node_info.node_type & p_rec->node_info.node_type ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0017: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected node_type 0x%X, received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ p_node->rec.node_info.node_type,
+ p_rec->node_info.node_type );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.sys_guid &
+ p_node->rec.node_info.sys_guid ) !=
+ ( p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0018: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected sys_guid 0x%016" PRIx64
+ ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh64( p_node->rec.node_info.sys_guid ),
+ cl_ntoh64( p_rec->node_info.sys_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.node_guid &
+ p_node->rec.node_info.node_guid ) !=
+ ( p_node->comp.node_info.node_guid & p_rec->node_info.node_guid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0019: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected node_guid 0x%016" PRIx64
+ ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh64( p_node->rec.node_info.node_guid ),
+ cl_ntoh64( p_rec->node_info.node_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.port_guid &
+ p_node->rec.node_info.port_guid ) !=
+ ( p_node->comp.node_info.port_guid & p_rec->node_info.port_guid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0031: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected port_guid 0x%016" PRIx64
+ ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh64( p_node->rec.node_info.port_guid ),
+ cl_ntoh64( p_rec->node_info.port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.partition_cap &
+ p_node->rec.node_info.partition_cap ) !=
+ ( p_node->comp.node_info.partition_cap &
+ p_rec->node_info.partition_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0032: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected partition_cap 0x%X"
+ ", received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh16( p_node->rec.node_info.partition_cap ),
+ cl_ntoh16( p_rec->node_info.partition_cap ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.device_id &
+ p_node->rec.node_info.device_id ) !=
+ ( p_node->comp.node_info.device_id & p_rec->node_info.device_id ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0033: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected device_id 0x%X"
+ ", received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh16( p_node->rec.node_info.device_id ),
+ cl_ntoh16( p_rec->node_info.device_id ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_node->comp.node_info.revision &
+ p_node->rec.node_info.revision ) !=
+ ( p_node->comp.node_info.revision & p_rec->node_info.revision ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_data: ERR 0034: "
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+ "\t\t\t\tExpected revision 0x%X"
+ ", received 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ),
+ cl_ntoh32( p_node->rec.node_info.revision ),
+ cl_ntoh32( p_rec->node_info.revision ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_rec( IN osmtest_t * const p_osmt,
+ IN const ib_node_record_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+ node_t *p_node;
+ const cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_rec );
+
+ /*
+ * Find proper node record in the database.
+ */
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+ p_node = ( node_t * ) cl_qmap_get( p_tbl, p_rec->lid );
+ if( p_node == ( node_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_node_rec: ERR 0035: "
+ "Unexpected node 0x%016" PRIx64 ", LID 0x%X.\n",
+ cl_ntoh64( p_rec->node_info.node_guid ),
+ cl_ntoh16( p_rec->lid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ status = osmtest_validate_node_data( p_osmt, p_node, p_rec );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_data( IN osmtest_t * const p_osmt,
+ IN port_t * const p_port,
+ IN const ib_portinfo_record_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_data );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: "
+ "Checking port LID 0x%X, Num 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num);
+ }
+
+ /*
+ * Has this record already been returned?
+ */
+ if( p_port->count != 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0036: "
+ "Already received port LID 0x%X, Num 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num);
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++p_port->count;
+
+ /*
+ * Compare the fields the user wishes to validate.
+ */
+ if( ( p_port->comp.lid & p_port->rec.lid ) !=
+ ( p_port->comp.lid & p_rec->lid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0037: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected LID 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.lid, p_rec->lid );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_port->comp.port_num & p_port->rec.port_num ) !=
+ ( p_port->comp.port_num & p_rec->port_num ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0038: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected port_num 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_num, p_rec->port_num );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( ( p_port->comp.port_info.m_key & p_port->rec.port_info.m_key ) !=
+ ( p_port->comp.port_info.m_key & p_rec->port_info.m_key ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0039: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected m_key 0x%016" PRIx64 ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.m_key, p_rec->port_info.m_key );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.subnet_prefix & p_port->rec.port_info.subnet_prefix ) !=
+ ( p_port->comp.port_info.subnet_prefix & p_rec->port_info.subnet_prefix ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0040: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected subnet_prefix 0x%016" PRIx64 ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.subnet_prefix, p_rec->port_info.subnet_prefix );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.base_lid & p_port->rec.port_info.base_lid ) !=
+ ( p_port->comp.port_info.base_lid & p_rec->port_info.base_lid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0041: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected base_lid 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.base_lid, p_rec->port_info.base_lid );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info.master_sm_base_lid ) !=
+ ( p_port->comp.port_info.master_sm_base_lid & p_rec->port_info.master_sm_base_lid ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0042: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.master_sm_base_lid, p_rec->port_info.master_sm_base_lid );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.capability_mask & p_port->rec.port_info.capability_mask ) !=
+ ( p_port->comp.port_info.capability_mask & p_rec->port_info.capability_mask ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0043: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected capability_mask 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.capability_mask, p_rec->port_info.capability_mask );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.diag_code & p_port->rec.port_info.diag_code ) !=
+ ( p_port->comp.port_info.diag_code & p_rec->port_info.diag_code ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0044: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected diag_code 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.diag_code, p_rec->port_info.diag_code );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info.m_key_lease_period ) !=
+ ( p_port->comp.port_info.m_key_lease_period & p_rec->port_info.m_key_lease_period ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0045: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.m_key_lease_period, p_rec->port_info.m_key_lease_period );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.local_port_num & p_port->rec.port_info.local_port_num ) !=
+ ( p_port->comp.port_info.local_port_num & p_rec->port_info.local_port_num ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0046: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected local_port_num 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.local_port_num, p_rec->port_info.local_port_num );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.link_width_enabled & p_port->rec.port_info.link_width_enabled ) !=
+ ( p_port->comp.port_info.link_width_enabled & p_rec->port_info.link_width_enabled ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0047: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.link_width_enabled, p_rec->port_info.link_width_enabled );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.link_width_supported & p_port->rec.port_info.link_width_supported ) !=
+ ( p_port->comp.port_info.link_width_supported & p_rec->port_info.link_width_supported ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0048: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected link_width_supported 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.link_width_supported, p_rec->port_info.link_width_supported );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.link_width_active & p_port->rec.port_info.link_width_active ) !=
+ ( p_port->comp.port_info.link_width_active & p_rec->port_info.link_width_active ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0049: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected link_width_active 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.link_width_active, p_rec->port_info.link_width_active );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=
+ ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0054: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected link_speed 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.state_info1 & p_port->rec.port_info.state_info1 ) !=
+ ( p_port->comp.port_info.state_info1 & p_rec->port_info.state_info1 ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0057: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected state_info1 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.state_info1, p_rec->port_info.state_info1 );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.state_info2 & p_port->rec.port_info.state_info2 ) !=
+ ( p_port->comp.port_info.state_info2 & p_rec->port_info.state_info2 ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0058: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected state_info2 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.state_info2, p_rec->port_info.state_info2 );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.mkey_lmc & p_port->rec.port_info.mkey_lmc ) !=
+ ( p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0059: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.mkey_lmc, p_rec->port_info.mkey_lmc );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=
+ ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0060: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected link_speed 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.mtu_smsl & p_port->rec.port_info.mtu_smsl ) !=
+ ( p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0061: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.mtu_smsl, p_rec->port_info.mtu_smsl );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap ) !=
+ ( p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0062: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_cap 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.vl_high_limit & p_port->rec.port_info.vl_high_limit ) !=
+ ( p_port->comp.port_info.vl_high_limit & p_rec->port_info.vl_high_limit ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0082: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_high_limit, p_rec->port_info.vl_high_limit );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info.vl_arb_high_cap ) !=
+ ( p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info.vl_arb_high_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0083: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_high_cap );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info.vl_arb_low_cap ) !=
+ ( p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info.vl_arb_low_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0084: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_arb_low_cap, p_rec->port_info.vl_arb_low_cap );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap ) !=
+ ( p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0085: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected mtu_cap 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.mtu_cap, p_rec->port_info.mtu_cap );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ /* this is a dynamic attribute
+ if( ( p_port->comp.port_info.vl_stall_life & p_port->rec.port_info.vl_stall_life ) !=
+ ( p_port->comp.port_info.vl_stall_life & p_rec->port_info.vl_stall_life ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0129: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_stall_life, p_rec->port_info.vl_stall_life );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ */
+
+ if( ( p_port->comp.port_info.vl_enforce & p_port->rec.port_info.vl_enforce ) !=
+ ( p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0086: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected vl_enforce 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.vl_enforce, p_rec->port_info.vl_enforce );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.m_key_violations & p_port->rec.port_info.m_key_violations ) !=
+ ( p_port->comp.port_info.m_key_violations & p_rec->port_info.m_key_violations ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0087: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected m_key_violations 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.m_key_violations, p_rec->port_info.m_key_violations );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.p_key_violations & p_port->rec.port_info.p_key_violations ) !=
+ ( p_port->comp.port_info.p_key_violations & p_rec->port_info.p_key_violations ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0088: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected p_key_violations 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.p_key_violations, p_rec->port_info.p_key_violations );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.q_key_violations & p_port->rec.port_info.q_key_violations ) !=
+ ( p_port->comp.port_info.q_key_violations & p_rec->port_info.q_key_violations ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0089: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected q_key_violations 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.q_key_violations, p_rec->port_info.q_key_violations );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.guid_cap & p_port->rec.port_info.guid_cap ) !=
+ ( p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0090: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected guid_cap 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.guid_cap, p_rec->port_info.guid_cap );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.subnet_timeout & p_port->rec.port_info.subnet_timeout ) !=
+ ( p_port->comp.port_info.subnet_timeout & p_rec->port_info.subnet_timeout ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0091: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ ib_port_info_get_timeout(&p_port->rec.port_info),
+ ib_port_info_get_timeout(&p_rec->port_info) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.resp_time_value & p_port->rec.port_info.resp_time_value ) !=
+ ( p_port->comp.port_info.resp_time_value & p_rec->port_info.resp_time_value ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0092: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected resp_time_value 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.resp_time_value, p_rec->port_info.resp_time_value );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+
+ if( ( p_port->comp.port_info.error_threshold & p_port->rec.port_info.error_threshold ) !=
+ ( p_port->comp.port_info.error_threshold & p_rec->port_info.error_threshold ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_data: ERR 0093: "
+ "Field mismatch port LID 0x%X Num:0x%X.\n"
+ "\t\t\t\tExpected error_threshold 0x%X, received 0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,
+ p_port->rec.port_info.error_threshold, p_rec->port_info.error_threshold );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_rec( IN osmtest_t * const p_osmt,
+ IN const ib_portinfo_record_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+ port_t *p_port;
+ const cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_rec );
+
+ /*
+ * Find proper port record in the database. (we use by guid - since lid is not unique)
+ */
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;
+ p_port = ( port_t * ) cl_qmap_get( p_tbl, port_gen_id( p_rec->lid, p_rec->port_num));
+ if( p_port == ( port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_port_rec: ERR 0094: "
+ "Unexpected port LID 0x%X, Num:0x%X.\n",
+ cl_ntoh16( p_rec->lid ), p_rec->port_num );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ status = osmtest_validate_port_data( p_osmt, p_port, p_rec );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_rec( IN osmtest_t * const p_osmt,
+ IN const ib_path_rec_t * const p_rec )
+{
+ cl_status_t status = IB_SUCCESS;
+ path_t *p_path;
+ const cl_qmap_t *p_tbl;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_rec );
+
+ /*
+ * Find proper path record in the database.
+ */
+ p_tbl = &p_osmt->exp_subn.path_tbl;
+ p_path =
+ ( path_t * ) cl_qmap_get( p_tbl, osmtest_path_rec_key_get( p_rec ) );
+ if( p_path == ( path_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_path_rec: ERR 0095: "
+ "Unexpected path SLID 0x%X to DLID 0x%X.\n",
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ status = osmtest_validate_path_data( p_osmt, p_path, p_rec );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_node_recs( IN osmtest_t * const p_osmt )
+{
+ osmtest_req_context_t context;
+ const ib_node_record_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_node_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all NodeRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_node_recs: ERR 0096: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_all_node_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ /*
+ * Compare the received records to the database.
+ */
+ osmtest_prepare_db( p_osmt );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+
+ status = osmtest_validate_node_rec( p_osmt, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_node_recs: ERR 0097: "
+ "osmtest_valid_node_rec failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ status = osmtest_check_missing_nodes( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_node_recs: ERR 0098: "
+ "osmtest_check_missing_nodes failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+#endif
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_path_recs( IN osmtest_t * const p_osmt )
+{
+ osmtest_req_context_t context;
+ const ib_path_rec_t *p_rec;
+ uint32_t i;
+ cl_status_t status;
+ size_t num_recs;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_path_recs );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ /*
+ * Do a blocking query for all PathRecords in the subnet.
+ */
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+ sizeof( *p_rec ), &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_path_recs: ERR 0099: "
+ "osmtest_get_all_recs failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_all_path_recs: "
+ "Received %u records.\n", num_recs );
+ }
+
+ /*
+ * Compare the received records to the database.
+ */
+ osmtest_prepare_db( p_osmt );
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+
+ status = osmtest_validate_path_rec( p_osmt, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_path_recs: ERR 00100: "
+ "osmtest_valid_node_rec failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ status = osmtest_check_missing_paths( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_all_path_recs: ERR 00101: "
+ "osmtest_check_missing_paths failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_rec_lid_pair( IN osmtest_t * const p_osmt,
+ IN path_t * const p_path )
+{
+ osmtest_req_context_t context;
+ const ib_path_rec_t *p_rec;
+ cl_status_t status = IB_SUCCESS;
+ size_t num_recs;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_lid_pair );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt,
+ p_path->rec.slid,
+ p_path->rec.dlid,
+ &context);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_lid_pair: ERR 00102: "
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+ if( num_recs != 1 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_lid_pair: ERR 00103: "
+ "Too many records. Expected 1, received %u.\n", num_recs );
+
+ status = IB_ERROR;
+ }
+ else
+ {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, 0 );
+
+ status = osmtest_validate_path_data( p_osmt, p_path, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_lid_pair: ERR 00104: "
+ "osmtest_validate_path_data failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_node_rec_lid( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const lid,
+ IN node_t * const p_node )
+{
+ cl_status_t status = IB_SUCCESS;
+ osmv_user_query_t user;
+ osmv_query_req_t req;
+ ib_node_record_t record;
+
+ osmtest_req_context_t context;
+ const ib_node_record_t *p_rec;
+ int num_recs, i;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_rec_lid );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_validate_single_node_rec_lid: "
+ "Getting NodeRecord for node with LID 0x%X.\n",
+ cl_ntoh16( lid ) );
+ }
+
+ cl_memclr( &context, sizeof( context ) );
+ cl_memclr( &req, sizeof( req ) );
+ cl_memclr( &user, sizeof( user ) );
+ cl_memclr( &record, sizeof( record ) );
+
+ record.lid = lid;
+
+ context.p_osmt = p_osmt;
+ user.comp_mask = IB_NR_COMPMASK_LID;
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+ user.attr_offset = cl_ntoh16( (uint16_t) ( sizeof( record ) >> 3 ) );
+ user.p_attr = &record;
+
+ req.query_type = OSMV_QUERY_USER_DEFINED;
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+ req.p_query_input = &user;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_node_rec_lid: ERR 00105: "
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_node_rec_lid: ERR 00106: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_node_rec_lid: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_node_rec_lid: "
+ "Received %d nodes\n", num_recs);
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+
+ status = osmtest_validate_node_rec( p_osmt, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_node_rec_lid: ERR 00107: "
+ "osmtest_validate_node_data failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_port_rec_lid( IN osmtest_t * const p_osmt,
+ IN port_t * const p_port )
+{
+ osmtest_req_context_t context;
+
+ const ib_portinfo_record_t *p_rec;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_rec_lid );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ context.p_osmt = p_osmt;
+ osmtest_get_port_rec_by_num( p_osmt,
+ p_port->rec.lid,
+ p_port->rec.port_num,
+ &context);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_port_rec_lid: ERR 00108: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ /* we should have got exactly one port */
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);
+ status = osmtest_validate_port_rec( p_osmt, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_port_rec_lid: ERR 00109: "
+ "osmtest_validate_port_data failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_rec_guid_pair( IN osmtest_t * const p_osmt,
+ IN const osmv_guid_pair_t *
+ const p_pair )
+{
+ osmtest_req_context_t context;
+ const ib_path_rec_t *p_rec;
+ cl_status_t status = IB_SUCCESS;
+ size_t num_recs;
+ osmv_query_req_t req;
+ uint32_t i;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_guid_pair );
+
+ cl_memclr( &context, sizeof( context ) );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: "
+ "\n\t\t\t\tChecking src 0x%016" PRIx64
+ " to dest 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_pair->src_guid ),
+ cl_ntoh64( p_pair->dest_guid ) );
+ }
+
+ context.p_osmt = p_osmt;
+
+ req.timeout_ms = p_osmt->opt.transaction_timeout;
+ req.retry_cnt = p_osmt->opt.retry_count;
+ req.flags = OSM_SA_FLAGS_SYNC;
+ req.query_context = &context;
+ req.pfn_query_cb = osmtest_query_res_cb;
+
+ req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+ req.p_query_input = p_pair;
+ req.sm_key = 0;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: ERR 00110: "
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = context.result.status;
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: ERR 00111: "
+ "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+ if( status == IB_REMOTE_ERROR )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: "
+ "Remote error = %s.\n",
+ ib_get_mad_status_str( osm_madw_get_mad_ptr
+ ( context.result.
+ p_result_madw ) ) );
+ }
+ goto Exit;
+ }
+
+ num_recs = context.result.result_cnt;
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_path_rec_guid_pair: "
+ "Got: %u records\n",
+ num_recs);
+
+ for( i = 0; i < num_recs; i++ )
+ {
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+
+ /*
+ * Make sure the GUID values are correct
+ */
+ if( p_rec->dgid.unicast.interface_id != p_pair->dest_guid )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: ERR 00112: "
+ "Destination GUID mismatch.\n"
+ "\t\t\t\texpected 0x%016" PRIx64
+ ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_pair->dest_guid ),
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ) );
+ }
+
+ if( p_rec->sgid.unicast.interface_id != p_pair->src_guid )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: ERR 00113: "
+ "Source GUID mismatch.\n"
+ "\t\t\t\texpected 0x%016" PRIx64
+ ", received 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_pair->src_guid ),
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ) );
+ }
+
+ status = osmtest_validate_path_rec( p_osmt, p_rec );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_rec_guid_pair: ERR 00114: "
+ "osmtest_validate_path_data failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ if (status != IB_SUCCESS )
+ {
+ osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+ }
+ }
+
+ Exit:
+ /*
+ * Return the IB query MAD to the pool as necessary.
+ */
+ if( context.result.p_result_madw != NULL )
+ {
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+ context.result.p_result_madw = NULL;
+ }
+
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_recs( IN osmtest_t * const p_osmt )
+{
+ path_t *p_path;
+ cl_status_t status = IB_SUCCESS;
+ const cl_qmap_t *p_path_tbl;
+/* We skip node to node path record validation since it might contains
+ UNEXISTANT PATHS , i.e when using UPDN */
+ osmv_guid_pair_t guid_pair;
+ uint16_t cnt;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_recs );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_path_recs: "
+ "Validating individual path record queries.\n" );
+ }
+ p_path_tbl = &p_osmt->exp_subn.path_tbl;
+
+ osmtest_prepare_db( p_osmt );
+
+ /*
+ * Walk the list of all path records, and ask for each one
+ * specifically. Make sure we get it.
+ */
+ cnt = 0;
+ p_path = ( path_t * ) cl_qmap_head( p_path_tbl );
+ while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )
+ {
+ status = osmtest_validate_single_path_rec_lid_pair( p_osmt, p_path );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ cnt++;
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_path_recs: "
+ "Total of %u path records validated using LID based query.\n", cnt );
+ }
+
+ status = osmtest_check_missing_paths( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_recs: ERR 00115: "
+ "osmtest_check_missing_paths failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /*
+ * Do the whole thing again with port GUID pairs.
+ * Note that multiple path records may be returned
+ * for each guid pair if LMC > 0.
+ */
+ osmtest_prepare_db( p_osmt );
+ cnt = 0;
+ p_path = ( path_t * ) cl_qmap_head( p_path_tbl );
+ while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )
+ {
+ guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id;
+ guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id;
+ status =
+ osmtest_validate_single_path_rec_guid_pair( p_osmt,
+ &guid_pair );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ cnt++;
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+ }
+
+
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_path_recs: "
+ "Total of %u path records validated using GUID based query.\n", cnt );
+ }
+
+ status = osmtest_check_missing_paths( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_path_recs: ERR 00116: "
+ "osmtest_check_missing_paths failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_node_recs( IN osmtest_t * const p_osmt )
+{
+ node_t *p_node;
+ cl_status_t status = IB_SUCCESS;
+ const cl_qmap_t *p_node_lid_tbl;
+ uint16_t cnt = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_recs );
+
+ p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+ osmtest_prepare_db( p_osmt );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_node_recs: "
+ "Validating individual node record queries.\n" );
+ }
+
+ /*
+ * Walk the list of all node records, and ask for each one
+ * specifically. Make sure we get it.
+ */
+ p_node = ( node_t * ) cl_qmap_head( p_node_lid_tbl );
+ while( p_node != ( node_t * ) cl_qmap_end( p_node_lid_tbl ) )
+ {
+ status = osmtest_validate_single_node_rec_lid( p_osmt,
+ (ib_net16_t) cl_qmap_key ((cl_map_item_t*)p_node),
+ p_node );
+ cnt++;
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_node_recs: "
+ "Total of %u node records validated.\n", cnt );
+ }
+
+ status = osmtest_check_missing_nodes( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_node_recs: ERR 00117: "
+ "osmtest_check_missing_nodes (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_port_recs( IN osmtest_t * const p_osmt )
+{
+ port_t *p_port;
+ cl_status_t status = IB_SUCCESS;
+ const cl_qmap_t *p_port_key_tbl;
+ uint16_t cnt = 0;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_recs );
+
+ p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+ osmtest_prepare_db( p_osmt );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_port_recs: "
+ "Validating individual port record queries.\n" );
+ }
+
+ /*
+ * Walk the list of all port records, and ask for each one
+ * specifically. Make sure we get it.
+ */
+ p_port = ( port_t * ) cl_qmap_head( p_port_key_tbl );
+ while( p_port != ( port_t * ) cl_qmap_end( p_port_key_tbl ) )
+ {
+ status = osmtest_validate_single_port_rec_lid( p_osmt, p_port );
+ cnt++;
+ p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );
+ }
+
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmtest_validate_single_port_recs: "
+ "Total of %u port records validated.\n", cnt );
+ }
+
+
+ status = osmtest_check_missing_ports( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_validate_single_port_recs: ERR 00118: "
+ "osmtest_check_missing_paths failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_against_db( IN osmtest_t * const p_osmt )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_against_db );
+
+#ifdef VENDOR_RMPP_SUPPORT
+ status = osmtest_validate_all_node_recs( p_osmt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+#endif
+
+ status = osmtest_validate_single_node_recs( p_osmt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+#ifdef VENDOR_RMPP_SUPPORT
+ if (! p_osmt->opt.ignore_path_records)
+ {
+ status = osmtest_validate_all_path_recs( p_osmt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ }
+#endif
+
+ status = osmtest_validate_single_port_recs( p_osmt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ if (! p_osmt->opt.ignore_path_records)
+ {
+ status = osmtest_validate_single_path_recs( p_osmt );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ }
+
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const osmtest_token_t *
+str_get_token( IN char *const p_str )
+{
+ const osmtest_token_t *p_tok;
+ uint32_t index = 0;
+
+ p_tok = &token_array[index];
+
+ while( p_tok->val != OSMTEST_TOKEN_UNKNOWN )
+ {
+ if( strnicmp( p_str, p_tok->str, p_tok->str_size ) == 0 )
+ return ( p_tok );
+
+ p_tok = &token_array[++index];
+ }
+
+ return ( NULL );
+}
+
+/**********************************************************************
+ Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static boolean_t
+str_skip_white( IN char line[],
+ IN OUT uint32_t * const p_offset )
+{
+ while( ( ( line[*p_offset] == '\t' ) ||
+ ( line[*p_offset] == ' ' ) ) &&
+ ( line[*p_offset] != '\n' ) && ( line[*p_offset] != '\0' ) )
+ {
+ ++*p_offset;
+ }
+
+ if( ( line[*p_offset] == '\n' ) || ( line[*p_offset] == '\0' ) )
+ return ( FALSE );
+ else
+ return ( TRUE );
+}
+
+/**********************************************************************
+ Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static void
+str_skip_token( IN char line[],
+ IN OUT uint32_t * const p_offset )
+{
+ while( ( line[*p_offset] != '\t' ) &&
+ ( line[*p_offset] != ' ' ) && ( line[*p_offset] != '\0' ) )
+ {
+ ++*p_offset;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_node( IN osmtest_t * const p_osmt,
+ IN FILE * const fh,
+ IN OUT uint32_t * const p_line_num )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint32_t offset;
+ char line[OSMTEST_MAX_LINE_LEN];
+ boolean_t done = FALSE;
+ node_t *p_node;
+ node_t *p_guid_node;
+ const osmtest_token_t *p_tok;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_node );
+
+ p_node = node_new( );
+ CL_ASSERT( p_node != NULL );
+
+ /*
+ * Parse the inventory file and create the database.
+ */
+ while( !done )
+ {
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+ {
+ /*
+ * End of file in the middle of a definition.
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_node: ERR 00119: "
+ "Unexpected end of file.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++*p_line_num;
+
+ /*
+ * Skip whitespace
+ */
+ offset = 0;
+ if( !str_skip_white( line, &offset ) )
+ continue; /* whole line was whitespace */
+
+ p_tok = str_get_token( &line[offset] );
+ if( p_tok == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_node: ERR 00120: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+ continue;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+ }
+
+ str_skip_token( line, &offset );
+
+ switch ( p_tok->val )
+ {
+ case OSMTEST_TOKEN_COMMENT:
+ break;
+
+ case OSMTEST_TOKEN_LID:
+ p_node->comp.lid = 0xFFFF;
+ p_node->rec.lid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "lid = 0x%X.\n", cl_ntoh16( p_node->rec.lid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_BASE_VERSION:
+ p_node->comp.node_info.base_version = 0xFF;
+ p_node->rec.node_info.base_version =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "base_version = 0x%X.\n",
+ p_node->rec.node_info.base_version );
+ }
+ break;
+
+ case OSMTEST_TOKEN_CLASS_VERSION:
+ p_node->comp.node_info.class_version = 0xFF;
+ p_node->rec.node_info.class_version =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "class_version = 0x%X.\n",
+ p_node->rec.node_info.class_version );
+ }
+ break;
+
+ case OSMTEST_TOKEN_NODE_TYPE:
+ p_node->comp.node_info.node_type = 0xFF;
+ p_node->rec.node_info.node_type =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "node_type = 0x%X.\n",
+ p_node->rec.node_info.node_type );
+ }
+ break;
+
+ case OSMTEST_TOKEN_NUM_PORTS:
+ p_node->comp.node_info.num_ports = 0xFF;
+ p_node->rec.node_info.num_ports =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "num_ports = 0x%X.\n",
+ p_node->rec.node_info.num_ports );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SYS_GUID:
+ p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL;
+ p_node->rec.node_info.sys_guid =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "sys_guid = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_node->rec.node_info.sys_guid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_NODE_GUID:
+ p_node->comp.node_info.node_guid = 0xFFFFFFFFFFFFFFFFULL;
+ p_node->rec.node_info.node_guid =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "node_guid = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PORT_GUID:
+ p_node->comp.node_info.port_guid = 0xFFFFFFFFFFFFFFFFULL;
+ p_node->rec.node_info.port_guid =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "port_guid = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_node->rec.node_info.port_guid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PARTITION_CAP:
+ p_node->comp.node_info.partition_cap = 0xFFFF;
+ p_node->rec.node_info.partition_cap = cl_hton16( ( uint16_t )
+ strtoul( &line
+ [offset],
+ NULL,
+ 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "partition_cap = 0x%X.\n",
+ cl_ntoh16( p_node->rec.node_info.partition_cap ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_DEVICE_ID:
+ p_node->comp.node_info.device_id = 0xFFFF;
+ p_node->rec.node_info.device_id = cl_hton16( ( uint16_t )
+ strtoul( &line
+ [offset],
+ NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "device_id = 0x%X.\n",
+ cl_ntoh16( p_node->rec.node_info.device_id ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_REVISION:
+ p_node->comp.node_info.revision = 0xFFFFFFFF;
+ p_node->rec.node_info.revision =
+ cl_hton32( strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "revision = 0x%X.\n",
+ cl_ntoh32( p_node->rec.node_info.revision ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PORT_NUM:
+ p_node->comp.node_info.port_num_vendor_id |=
+ IB_NODE_INFO_PORT_NUM_MASK;
+ p_node->rec.node_info.port_num_vendor_id |=
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "local_port_num = 0x%X.\n",
+ ib_node_info_get_local_port_num( &p_node->rec.
+ node_info ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VENDOR_ID:
+ p_node->comp.node_info.port_num_vendor_id |=
+ IB_NODE_INFO_VEND_ID_MASK;
+ p_node->rec.node_info.port_num_vendor_id |=
+ cl_hton32( strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_node: "
+ "vendor_id = 0x%X.\n",
+ cl_ntoh32( ib_node_info_get_vendor_id
+ ( &p_node->rec.node_info ) ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_END:
+ done = TRUE;
+ break;
+
+ default:
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_node: ERR 00121: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+
+ break;
+ }
+ }
+
+ /*
+ * Make sure the user specified enough information, then
+ * add this object to the database.
+ */
+ if( p_node->comp.lid == 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_node: ERR 00122: "
+ "LID must be specified for defined nodes.\n" );
+ node_delete( p_node );
+ goto Exit;
+ }
+
+ cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,
+ p_node->rec.lid, &p_node->map_item );
+
+ p_guid_node = node_new( );
+ CL_ASSERT( p_node != NULL );
+
+ *p_guid_node = *p_node;
+
+ cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,
+ p_guid_node->rec.node_info.node_guid,
+ &p_guid_node->map_item );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_port( IN osmtest_t * const p_osmt,
+ IN FILE * const fh,
+ IN OUT uint32_t * const p_line_num )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint32_t offset;
+ char line[OSMTEST_MAX_LINE_LEN];
+ boolean_t done = FALSE;
+ port_t *p_port;
+ const osmtest_token_t *p_tok;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_port );
+
+ p_port = port_new( );
+ CL_ASSERT( p_port != NULL );
+
+ /*
+ * Parse the inventory file and create the database.
+ */
+ while( !done )
+ {
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+ {
+ /*
+ * End of file in the middle of a definition.
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_port: ERR 00123: "
+ "Unexpected end of file.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++*p_line_num;
+
+ /*
+ * Skip whitespace
+ */
+ offset = 0;
+ if( !str_skip_white( line, &offset ) )
+ continue; /* whole line was whitespace */
+
+ p_tok = str_get_token( &line[offset] );
+ if( p_tok == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_port: ERR 00124: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+ continue;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+ }
+
+ str_skip_token( line, &offset );
+
+ switch ( p_tok->val )
+ {
+ case OSMTEST_TOKEN_COMMENT:
+ break;
+
+ case OSMTEST_TOKEN_LID:
+ p_port->comp.lid = 0xFFFF;
+ p_port->rec.lid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "lid = 0x%X.\n", cl_ntoh16( p_port->rec.lid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PORT_NUM:
+ p_port->comp.port_num = 0xFF;
+ p_port->rec.port_num =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "port_num = 0x%u.\n",
+ p_port->rec.port_num );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MKEY:
+ p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL;
+ p_port->rec.port_info.m_key =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "m_key = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_port->rec.port_info.m_key ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SUBN_PREF:
+ p_port->comp.port_info.subnet_prefix = 0xFFFFFFFFFFFFFFFFULL;
+ p_port->rec.port_info.subnet_prefix =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "subnet_prefix = 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_port->rec.port_info.subnet_prefix ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_BASE_LID:
+ p_port->comp.port_info.base_lid = 0xFFFF;
+ p_port->rec.port_info.base_lid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "base_lid = 0x%X.\n", cl_ntoh16( p_port->rec.port_info.base_lid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SM_BASE_LID:
+ p_port->comp.port_info.master_sm_base_lid = 0xFFFF;
+ p_port->rec.port_info.master_sm_base_lid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "master_sm_base_lid = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.master_sm_base_lid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_CAP_MASK:
+ p_port->comp.port_info.capability_mask = 0xFFFFFFFF;
+ p_port->rec.port_info.capability_mask =
+ cl_hton32( ( uint32_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "capability_mask = 0x%X.\n",
+ cl_ntoh32( p_port->rec.port_info.capability_mask ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_DIAG_CODE:
+ p_port->comp.port_info.diag_code = 0xFFFF;
+ p_port->rec.port_info.diag_code =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "diag_code = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.diag_code ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MKEY_LEASE_PER:
+ p_port->comp.port_info.m_key_lease_period = 0xFFFF;
+ p_port->rec.port_info.m_key_lease_period =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "m_key_lease_period = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.m_key_lease_period ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LOC_PORT_NUM:
+ p_port->comp.port_info.local_port_num = 0xFF;
+ p_port->rec.port_info.local_port_num =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "local_port_num = 0x%u.\n",
+ p_port->rec.port_info.local_port_num );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LINK_WID_EN:
+ p_port->comp.port_info.link_width_enabled = 0xFF;
+ p_port->rec.port_info.link_width_enabled =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "link_width_enabled = 0x%u.\n",
+ p_port->rec.port_info.link_width_enabled );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LINK_WID_SUP:
+ p_port->comp.port_info.link_width_supported = 0xFF;
+ p_port->rec.port_info.link_width_supported =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "link_width_supported = 0x%u.\n",
+ p_port->rec.port_info.link_width_supported );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LINK_WID_ACT:
+ p_port->comp.port_info.link_width_active = 0xFF;
+ p_port->rec.port_info.link_width_active =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "link_width_active = 0x%u.\n",
+ p_port->rec.port_info.link_width_active );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LINK_SPEED_SUP:
+ p_port->comp.port_info.state_info1 = 0xFF;
+ ib_port_info_set_link_speed_sup(
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 ),
+ &p_port->rec.port_info);
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "link_speed_supported = 0x%u.\n",
+ ib_port_info_get_link_speed_sup(&p_port->rec.port_info));
+ }
+ break;
+
+ case OSMTEST_TOKEN_PORT_STATE:
+ str_skip_white( line, &offset );
+ p_port->comp.port_info.state_info1 = 0xFF;
+ ib_port_info_set_port_state(&p_port->rec.port_info,
+ ib_get_port_state_from_str(&line[offset]));
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "port_state = 0x%u.\n",
+ ib_port_info_get_port_state(&p_port->rec.port_info));
+ }
+ break;
+
+ case OSMTEST_TOKEN_STATE_INFO2:
+ p_port->comp.port_info.state_info2 = 0xFF;
+ p_port->rec.port_info.state_info2 =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "state_info2 = 0x%u.\n",
+ p_port->rec.port_info.state_info2 );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MKEY_PROT_BITS:
+ p_port->comp.port_info.mkey_lmc = 0xFF;
+ ib_port_info_set_mpb(
+ &p_port->rec.port_info,
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 ));
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "mpb = 0x%u.\n",
+ ib_port_info_get_mpb(&p_port->rec.port_info) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LMC:
+ p_port->comp.port_info.mkey_lmc = 0xFF;
+ ib_port_info_set_lmc(
+ &p_port->rec.port_info,
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "lmc = 0x%u.\n",
+ ib_port_info_get_lmc(&p_port->rec.port_info) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_LINK_SPEED:
+ p_port->comp.port_info.link_speed = 0xFF;
+ p_port->rec.port_info.link_speed =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "link_speed = 0x%u.\n",
+ p_port->rec.port_info.link_speed );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MTU_SMSL:
+ p_port->comp.port_info.mtu_smsl = 0xFF;
+ p_port->rec.port_info.mtu_smsl =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "mtu_smsl = 0x%u.\n",
+ p_port->rec.port_info.mtu_smsl );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_CAP:
+ p_port->comp.port_info.vl_cap = 0xFF;
+ p_port->rec.port_info.vl_cap =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_cap = 0x%u.\n",
+ p_port->rec.port_info.vl_cap );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_HIGH_LIMIT:
+ p_port->comp.port_info.vl_high_limit = 0xFF;
+ p_port->rec.port_info.vl_high_limit =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_high_limit = 0x%u.\n",
+ p_port->rec.port_info.vl_high_limit );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_ARB_HIGH_CAP:
+ p_port->comp.port_info.vl_arb_high_cap = 0xFF;
+ p_port->rec.port_info.vl_arb_high_cap =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_arb_high_cap = 0x%u.\n",
+ p_port->rec.port_info.vl_arb_high_cap );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_ARB_LOW_CAP:
+ p_port->comp.port_info.vl_arb_low_cap = 0xFF;
+ p_port->rec.port_info.vl_arb_low_cap =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_arb_low_cap = 0x%u.\n",
+ p_port->rec.port_info.vl_arb_low_cap );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MTU_CAP:
+ p_port->comp.port_info.mtu_cap = 0xFF;
+ p_port->rec.port_info.mtu_cap =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "mtu_cap = 0x%u.\n",
+ p_port->rec.port_info.mtu_cap );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_STALL_LIFE:
+ p_port->comp.port_info.vl_stall_life = 0xFF;
+ p_port->rec.port_info.vl_stall_life =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_stall_life = 0x%u.\n",
+ p_port->rec.port_info.vl_stall_life );
+ }
+ break;
+
+ case OSMTEST_TOKEN_VL_ENFORCE:
+ p_port->comp.port_info.vl_enforce = 0xFF;
+ p_port->rec.port_info.vl_enforce =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "vl_enforce = 0x%u.\n",
+ p_port->rec.port_info.vl_enforce );
+ }
+ break;
+
+ case OSMTEST_TOKEN_MKEY_VIOL:
+ p_port->comp.port_info.m_key_violations = 0xFFFF;
+ p_port->rec.port_info.m_key_violations =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "m_key_violations = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.m_key_violations ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PKEY_VIOL:
+ p_port->comp.port_info.p_key_violations = 0xFFFF;
+ p_port->rec.port_info.p_key_violations =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "p_key_violations = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.p_key_violations ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_QKEY_VIOL:
+ p_port->comp.port_info.q_key_violations = 0xFFFF;
+ p_port->rec.port_info.q_key_violations =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "q_key_violations = 0x%X.\n",
+ cl_ntoh16( p_port->rec.port_info.q_key_violations ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_GUID_CAP:
+ p_port->comp.port_info.guid_cap = 0xFF;
+ p_port->rec.port_info.guid_cap =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "guid_cap = 0x%u.\n",
+ p_port->rec.port_info.guid_cap );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SUBN_TIMEOUT:
+ p_port->comp.port_info.subnet_timeout = 0x1F;
+ p_port->rec.port_info.subnet_timeout =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "subnet_timeout = 0x%u.\n",
+ ib_port_info_get_timeout(&p_port->rec.port_info) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_RESP_TIME_VAL:
+ p_port->comp.port_info.resp_time_value = 0xFF;
+ p_port->rec.port_info.resp_time_value =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "resp_time_value = 0x%u.\n",
+ p_port->rec.port_info.resp_time_value );
+ }
+ break;
+
+ case OSMTEST_TOKEN_ERR_THRESHOLD:
+ p_port->comp.port_info.error_threshold = 0xFF;
+ p_port->rec.port_info.error_threshold =
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_port: "
+ "error_threshold = 0x%u.\n",
+ p_port->rec.port_info.error_threshold );
+ }
+ break;
+
+ case OSMTEST_TOKEN_END:
+ done = TRUE;
+ break;
+
+ default:
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_port: ERR 00125: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+
+ break;
+ }
+ }
+
+ /*
+ * Make sure the user specified enough information, then
+ * add this object to the database.
+ */
+ if( p_port->comp.lid == 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_port: ERR 00126: "
+ "LID must be specified for defined ports.\n" );
+ port_delete( p_port );
+ goto Exit;
+ }
+
+ cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,
+ port_gen_id(p_port->rec.lid, p_port->rec.port_num),
+ &p_port->map_item );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_path( IN osmtest_t * const p_osmt,
+ IN FILE * const fh,
+ IN OUT uint32_t * const p_line_num )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ uint32_t offset;
+ char line[OSMTEST_MAX_LINE_LEN];
+ boolean_t done = FALSE;
+ path_t *p_path;
+ const osmtest_token_t *p_tok;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_path );
+
+ p_path = path_new( );
+ CL_ASSERT( p_path != NULL );
+
+ /*
+ * Parse the inventory file and create the database.
+ */
+ while( !done )
+ {
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+ {
+ /*
+ * End of file in the middle of a definition.
+ */
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_path: ERR 00127: "
+ "Unexpected end of file.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ ++*p_line_num;
+
+ /*
+ * Skip whitespace
+ */
+ offset = 0;
+ if( !str_skip_white( line, &offset ) )
+ continue; /* whole line was whitespace */
+
+ p_tok = str_get_token( &line[offset] );
+ if( p_tok == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_path: ERR 00128: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+ continue;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+ }
+
+ str_skip_token( line, &offset );
+
+ switch ( p_tok->val )
+ {
+ case OSMTEST_TOKEN_COMMENT:
+ break;
+
+ case OSMTEST_TOKEN_DGID:
+ p_path->comp.dgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;
+ p_path->comp.dgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;
+
+ str_skip_white( line, &offset );
+ p_path->rec.dgid.unicast.prefix =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ str_skip_token( line, &offset );
+ p_path->rec.dgid.unicast.interface_id =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "dgid = 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_path->rec.dgid.unicast.prefix ),
+ cl_ntoh64( p_path->rec.dgid.unicast.interface_id ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SGID:
+ p_path->comp.sgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;
+ p_path->comp.sgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;
+
+ str_skip_white( line, &offset );
+ p_path->rec.sgid.unicast.prefix =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+ str_skip_token( line, &offset );
+ p_path->rec.sgid.unicast.interface_id =
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "sgid = 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+ cl_ntoh64( p_path->rec.sgid.unicast.prefix ),
+ cl_ntoh64( p_path->rec.sgid.unicast.interface_id ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_DLID:
+ p_path->comp.dlid = 0xFFFF;
+ p_path->rec.dlid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "dlid = 0x%X.\n", cl_ntoh16( p_path->rec.dlid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_SLID:
+ p_path->comp.slid = 0xFFFF;
+ p_path->rec.slid =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "slid = 0x%X.\n", cl_ntoh16( p_path->rec.slid ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_PKEY:
+ p_path->comp.pkey = 0xFFFF;
+ p_path->rec.pkey =
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_parse_path: "
+ "pkey = 0x%X.\n", cl_ntoh16( p_path->rec.pkey ) );
+ }
+ break;
+
+ case OSMTEST_TOKEN_END:
+ done = TRUE;
+ break;
+
+ default:
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_parse_path: ERR 00129: "
+ "Ignoring line %u with unknown token: %s.\n",
+ *p_line_num, &line[offset] );
+
+ break;
+ }
+ }
+
+ /*
+ * Make sure the user specified enough information, then
+ * add this object to the database.
+ */
+ if( osmtest_path_rec_kay_is_valid( p_osmt, p_path ) == FALSE )
+ {
+ path_delete( p_path );
+ goto Exit;
+ }
+
+ cl_qmap_insert( &p_osmt->exp_subn.path_tbl,
+ osmtest_path_rec_key_get( &p_path->rec ),
+ &p_path->map_item );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_create_db( IN osmtest_t * const p_osmt )
+{
+ FILE *fh;
+ ib_api_status_t status = IB_SUCCESS;
+ uint32_t offset;
+ char line[OSMTEST_MAX_LINE_LEN];
+ uint32_t line_num = 0;
+ const osmtest_token_t *p_tok;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_create_db );
+
+ fh = fopen( p_osmt->opt.file_name, "r" );
+ if( fh == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_create_db: ERR 00130: "
+ "Unable to open inventory file (%s).\n" ,p_osmt->opt.file_name);
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Parse the inventory file and create the database.
+ */
+ while( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) != NULL )
+ {
+ line_num++;
+
+ /*
+ * Skip whitespace
+ */
+ offset = 0;
+ if( !str_skip_white( line, &offset ) )
+ continue; /* whole line was whitespace */
+
+ p_tok = str_get_token( &line[offset] );
+ if( p_tok == NULL )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_create_db: ERR 00131: "
+ "Ignoring line %u: %s.\n", line_num, &line[offset] );
+ continue;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_create_db: "
+ "Found '%s' (line %u).\n", p_tok->str, line_num );
+ }
+
+ switch ( p_tok->val )
+ {
+ case OSMTEST_TOKEN_COMMENT:
+ break;
+
+ case OSMTEST_TOKEN_DEFINE_NODE:
+ status = osmtest_parse_node( p_osmt, fh, &line_num );
+ break;
+
+ case OSMTEST_TOKEN_DEFINE_PORT:
+ status = osmtest_parse_port( p_osmt, fh, &line_num );
+ break;
+
+ case OSMTEST_TOKEN_DEFINE_PATH:
+ status = osmtest_parse_path( p_osmt, fh, &line_num );
+ break;
+
+ default:
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_create_db: ERR 00132: "
+ "Ignoring line %u: %s.\n", line_num, &line[offset] );
+ break;
+ }
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_create_db: ERR 00133: "
+ "Bad status received during parsing (%s).\n",
+ ib_get_err_str( status ) );
+ fclose( fh );
+ goto Exit;
+ }
+ }
+
+ fclose( fh );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ Returns the index in the local port attribute array for the
+ user's selection.
+**********************************************************************/
+static uint32_t
+osmtest_get_user_port( IN osmtest_t * const p_osmt,
+ IN const ib_port_attr_t p_attr_array[],
+ IN uint32_t const num_ports )
+{
+ uint32_t i;
+ uint32_t choice = 0;
+ boolean_t done_flag = FALSE;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_user_port );
+
+ /*
+ * User needs prompting for the local port GUID with which
+ * to bind.
+ */
+
+ while( done_flag == FALSE )
+ {
+ printf( "\nChoose a local port number with which to bind:\n\n" );
+ for( i = 0; i < num_ports; i++ )
+ {
+ /*
+ * Print the index + 1 since by convention, port numbers
+ * start with 1 on host channel adapters.
+ */
+
+ printf( "\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+ i + 1, cl_ntoh64( p_attr_array[i].port_guid ),
+ p_attr_array[i].lid,
+ ib_get_port_state_str( p_attr_array[i].link_state ) );
+ }
+
+ printf( "\nEnter choice (1-%u): ", i );
+ scanf( "%u", &choice );
+ if( choice > num_ports )
+ printf( "\nError: Lame choice!\n" );
+ else
+ done_flag = TRUE;
+
+ }
+ printf("\n");
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( choice - 1 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_bind( IN osmtest_t * p_osmt,
+ IN uint16_t max_lid,
+ IN ib_net64_t guid OPTIONAL )
+{
+ uint32_t port_index;
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_bind );
+
+ /*
+ * Call the transport layer for a list of local port
+ * GUID values.
+ */
+ status = osm_vendor_get_all_port_attr( p_osmt->p_vendor,
+ attr_array, &num_ports );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_bind: ERR 00134: "
+ "Failure getting local port attributes (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ if( guid == 0 )
+ {
+ /*
+ * User needs prompting for the local port GUID with which
+ * to bind.
+ */
+ port_index = osmtest_get_user_port( p_osmt, attr_array, num_ports );
+
+ if( num_ports == 0 )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_bind: ERR 00135: "
+ "No local ports. Unable to proceed.\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ guid = attr_array[port_index].port_guid;
+ }
+ else
+ {
+ for( port_index = 0; port_index < num_ports; port_index++ )
+ {
+ if( attr_array[port_index].port_guid == guid )
+ break;
+ }
+
+ if( port_index == num_ports )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_bind: ERR 00136: "
+ "No local port with guid 0x%016" PRIx64 ".\n",
+ cl_ntoh64( guid ) );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ /*
+ * Copy the port info for the selected port.
+ */
+ cl_memcpy( &p_osmt->local_port, &attr_array[port_index],
+ sizeof( p_osmt->local_port ) );
+
+ /* bind to the SA */
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmtest_bind: "
+ "Using port SM_LID:0x%04X\n",
+ p_osmt->local_port.sm_lid);
+ p_osmt->max_lid = max_lid;
+
+ p_osmt->h_bind =
+ osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid);
+
+ if( p_osmt->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_bind: ERR 00137: " "Unable to bind to SA\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_run( IN osmtest_t * const p_osmt )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_run );
+
+ status = osmtest_validate_sa_class_port_info(p_osmt);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00138: "
+ "Could not obtain SA ClassPortInfo (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ if( p_osmt->opt.flow == 1 )
+ {
+ status = osmtest_create_inventory_file( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00139: "
+ "Inventory file create failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ if( p_osmt->opt.flow == 5 )
+ {
+ switch ( p_osmt->opt.stress )
+ {
+ case 0:
+ case 1: /* small response SA query stress */
+ status = osmtest_stress_small_rmpp( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00140: "
+ "Small RMPP stress test failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ break;
+ case 2: /* large response SA query stress */
+ status = osmtest_stress_large_rmpp( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00141: "
+ "Large RMPP stress test failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ break;
+ case 3: /* large response Path Record SA query stress */
+ status = osmtest_create_db( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00143: "
+ "Database creation failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = osmtest_stress_large_rmpp_pr( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00142: "
+ "Large RMPP stress test failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ break;
+ default:
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00143: "
+ "Unknown stress test value %u.\n",
+ p_osmt->opt.stress );
+ break;
+ }
+ }
+ else
+ {
+
+ /*
+ * Run normal validition tests.
+ */
+ if (!p_osmt->opt.flow || p_osmt->opt.flow == 2)
+ {
+ status = osmtest_create_db( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00143: "
+ "Database creation failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ status = osmtest_validate_against_db( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00144: "
+ "SA validation again database failure (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ if (!p_osmt->opt.flow)
+ {
+ status = osmtest_wrong_sm_key_ignored( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00145: "
+ "Try wrong SM_Key failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ if (!p_osmt->opt.flow || p_osmt->opt.flow == 3)
+ {
+ status = osmt_run_service_records_flow( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00146: "
+ "Service Flow failed (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+#ifdef OSM_VENDOR_INTF_MTL /* only available for now on mVAPI */
+ if (!p_osmt->opt.flow || p_osmt->opt.flow == 4)
+ {
+ status = osmt_run_inform_info_flow( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00147: "
+ "Inform Info Flow Failed: (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ /*
+ * since it generate a huge file - we run it only
+ * if explicitly required to
+ */
+ if (p_osmt->opt.flow == 7)
+ {
+ status = osmt_run_slvl_and_vlarb_records_flow(p_osmt);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00148: "
+ "Fail to get SLtoVL and VL Arbitration Tables (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ if (p_osmt->opt.flow == 8)
+ {
+ status = osmt_run_trap64_65_flow( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00150: "
+ "Trap 64/65 Flow Failed: (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+#endif
+
+ if (!p_osmt->opt.flow || p_osmt->opt.flow == 6)
+ {
+ status = osmt_run_mcast_flow( p_osmt );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmtest_run: ERR 00149: "
+ "Multicast Flow Failed: (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmtest_run: "
+ "\n\n***************** ALL TESTS PASS *****************\n\n" );
+
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return ( status );
+}
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSMTEST_H_
+#define _OSMTEST_H_
+
+#include <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include "osmtest_base.h"
+#include "osmtest_subnet.h"
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+/****s* OpenSM: Subnet/osmtest_opt_t
+ * NAME
+ * osmtest_opt_t
+ *
+ * DESCRIPTION
+ * Subnet options structure. This structure contains the various
+ * site specific configuration parameters for osmtest.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest_opt
+{
+ uint32_t transaction_timeout;
+ boolean_t force_log_flush;
+ boolean_t create;
+ uint32_t retry_count;
+ uint32_t stress;
+ uint32_t mmode;
+ char file_name[OSMTEST_FILE_PATH_MAX];
+ uint8_t flow;
+ uint8_t wait_time;
+ char *log_file;
+ boolean_t ignore_path_records;
+}
+osmtest_opt_t;
+
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ *********/
+
+/****h* OSMTest/OSMTest
+ * NAME
+ * OSMTest
+ *
+ * DESCRIPTION
+ * The OSMTest object tests an SM/SA for conformance to a known
+ * set of data about an Infiniband subnet.
+ *
+ * AUTHOR
+ * Steve King, Intel
+ *
+ *********/
+
+
+
+/****s* OSMTest/osmtest_t
+ * NAME
+ * osmtest_t
+ *
+ * DESCRIPTION
+ * OSMTest structure.
+ *
+ * This object should be treated as opaque and should
+ * be manipulated only through the provided functions.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest
+{
+ osm_log_t log;
+ struct _osm_vendor *p_vendor;
+ osm_bind_handle_t h_bind;
+ osm_mad_pool_t mad_pool;
+
+ osmtest_opt_t opt;
+ ib_port_attr_t local_port;
+ subnet_t exp_subn;
+ cl_qpool_t node_pool;
+ cl_qpool_t port_pool;
+ cl_qpool_t link_pool;
+
+ uint16_t max_lid;
+}
+osmtest_t;
+
+/*
+ * FIELDS
+ * log
+ * Log facility used by all OSMTest components.
+ *
+ * p_vendor
+ * Pointer to the vendor transport layer.
+ *
+ * h_bind
+ * The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa
+ *
+ * mad_pool
+ * The mad pool provided for teh vendor layer to allocate mad wrappers in
+ *
+ * opt
+ * osmtest options structure
+ *
+ * local_port
+ * Port attributes for the port over which osmtest is running.
+ *
+ * exp_subn
+ * Subnet object representing the expected subnet
+ *
+ * node_pool
+ * Pool of objects for use in populating the subnet databases.
+ *
+ * port_pool
+ * Pool of objects for use in populating the subnet databases.
+ *
+ * link_pool
+ * Pool of objects for use in populating the subnet databases.
+ *
+ * SEE ALSO
+ *********/
+
+/****s* OpenSM: Subnet/osmtest_req_context_t
+ * NAME
+ * osmtest_req_context_t
+ *
+ * DESCRIPTION
+ * Query context for ib_query callback function.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest_req_context
+{
+ osmtest_t *p_osmt;
+ osmv_query_res_t result;
+
+}
+osmtest_req_context_t;
+
+
+
+
+typedef struct _osmtest_mgrp_t
+{
+ cl_map_item_t map_item;
+ ib_member_rec_t mcmember_rec;
+} osmtest_mgrp_t;
+
+
+
+
+
+
+
+
+
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_construct
+ * NAME
+ * osmtest_construct
+ *
+ * DESCRIPTION
+ * This function constructs an OSMTest object.
+ *
+ * SYNOPSIS
+ */
+void osmtest_construct( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to a OSMTest object to construct.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Allows calling osmtest_init, osmtest_destroy.
+ *
+ * Calling osmtest_construct is a prerequisite to calling any other
+ * method except osmtest_init.
+ *
+ * SEE ALSO
+ * SM object, osmtest_init, osmtest_destroy
+ *********/
+
+/****f* OSMTest/osmtest_destroy
+ * NAME
+ * osmtest_destroy
+ *
+ * DESCRIPTION
+ * The osmtest_destroy function destroys an osmtest object, releasing
+ * all resources.
+ *
+ * SYNOPSIS
+ */
+void osmtest_destroy( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to a OSMTest object to destroy.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Performs any necessary cleanup of the specified OSMTest object.
+ * Further operations should not be attempted on the destroyed object.
+ * This function should only be called after a call to osmtest_construct or
+ * osmtest_init.
+ *
+ * SEE ALSO
+ * SM object, osmtest_construct, osmtest_init
+ *********/
+
+/****f* OSMTest/osmtest_init
+ * NAME
+ * osmtest_init
+ *
+ * DESCRIPTION
+ * The osmtest_init function initializes a OSMTest object for use.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_init( IN osmtest_t * const p_osmt,
+ IN const osmtest_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to an osmtest_t object to initialize.
+ *
+ * p_opt
+ * [in] Pointer to the options structure.
+ *
+ * log_flags
+ * [in] Log level flags to set.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if the OSMTest object was initialized successfully.
+ *
+ * NOTES
+ * Allows calling other OSMTest methods.
+ *
+ * SEE ALSO
+ * SM object, osmtest_construct, osmtest_destroy
+ *********/
+
+/****f* OSMTest/osmtest_run
+ * NAME
+ * osmtest_run
+ *
+ * DESCRIPTION
+ * Runs the osmtest suite.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_run( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to an osmtest_t object.
+ *
+ * guid
+ * [in] Port GUID over which to run the test suite.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_bind
+ * NAME
+ * osmtest_bind
+ *
+ * DESCRIPTION
+ * Binds osmtest to a local port.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_bind( IN osmtest_t * p_osmt,
+ IN uint16_t max_lid,
+ IN ib_net64_t guid OPTIONAL );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to an osmtest_t object.
+ *
+ * max_lid
+ * [in] The maximal lid to query about (if RMPP is not supported)
+ *
+ * guid
+ * [in] Port GUID over which to run the test suite.
+ * If zero, the bind function will display a menu of local
+ * port guids and wait for user input.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_query_res_cb
+ * NAME
+ * osmtest_query_res_cb
+ *
+ * DESCRIPTION
+ * A Callback for the query to invoke on completion
+ *
+ * SYNOPSIS
+ */
+void
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec );
+/*
+ * PARAMETERS
+ * p_rec
+ * [in] Pointer to an ib_query_rec_t object used for the query.
+ *
+ * RETURN VALUES
+ * NONE
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/ib_get_mad_status_str
+ * NAME
+ * ib_get_mad_status_str
+ *
+ * DESCRIPTION
+ * return the string representing the given mad status
+ *
+ * SYNOPSIS
+ */
+const char *
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad );
+/*
+ * PARAMETERS
+ * p_mad
+ * [in] Pointer to the mad payload
+ *
+ * RETURN VALUES
+ * NONE
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmt_run_service_records_flow
+ * NAME
+ * osmt_run_service_records_flow
+ *
+ * DESCRIPTION
+ * Run the service record testing flow.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmt_run_service_records_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+ib_api_status_t
+osmt_run_inform_info_flow( IN osmtest_t * const p_osmt );
+
+/****f* OSMTest/osmt_run_slvl_and_vlarb_records_flow
+ * NAME
+ * osmt_run_slvl_and_vlarb_records_flow
+ *
+ * DESCRIPTION
+ * Run the sl2vl and vlarb tables testing flow.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+
+/****f* OSMTest/osmt_run_mcast_flow
+ * NAME
+ * osmt_run_mcast_flow
+ *
+ * DESCRIPTION
+ * Run the multicast test flow
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+ osmt_run_mcast_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmt_run_trap64_65_flow
+ * NAME
+ * osmt_run_trap64_65_flow
+ *
+ * DESCRIPTION
+ * Run the trap 64/65 test flow. This test is ran with
+ * an outside tool.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ * p_osmt
+ * [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+ib_api_status_t
+osmtest_get_all_recs( IN osmtest_t * const p_osmt,
+ IN ib_net16_t const attr_id,
+ IN size_t const attr_size,
+ IN OUT osmtest_req_context_t * const p_context );
+#endif /* _OSMTEST_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+#ifndef _OSMTEST_BASE_H_
+#define _OSMTEST_BASE_H_
+
+#ifndef __WIN__
+#include <limits.h>
+#else
+#include <vendor/winosm_common.h>
+#endif
+
+#define OSMTEST_MAX_LINE_LEN 120
+#ifdef WIN32
+#define OSMTEST_FILE_PATH_MAX 4096
+#else
+#define OSMTEST_FILE_PATH_MAX PATH_MAX
+#endif
+#define STRESS_SMALL_RMPP_THR 100000
+/*
+ Take long times when quering big clusters (over 40 nodes) , an average of : 0.25 sec for query
+ each query receives 1000 records
+*/
+#define STRESS_LARGE_RMPP_THR 4000
+#define STRESS_LARGE_PR_RMPP_THR 20000
+extern const char *const p_file;
+
+#endif /* _OSMTEST_BASE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSMTEST_SUBNET_H_
+#define _OSMTEST_SUBNET_H_
+
+#include <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_log.h>
+
+
+/****s* Subnet Database/generic_t
+* NAME
+* generic_t
+*
+* DESCRIPTION
+* Subnet database object for fields common to all record types.
+* All other database types must be castable to this type.
+*
+* SYNOPSIS
+*/
+typedef struct _generic
+{
+ cl_map_item_t map_item; /* must be first element! */
+ uint32_t count; /* must be second element! */
+
+}
+generic_t;
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****s* Subnet Database/node_t
+* NAME
+* node_t
+*
+* DESCRIPTION
+* Subnet database object for nodes.
+* Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _node
+{
+ cl_map_item_t map_item; /* must be first element! */
+ uint32_t count; /* must be second element! */
+ ib_node_record_t rec;
+ ib_node_record_t comp;
+
+}
+node_t;
+
+/*
+* FIELDS
+* map_item
+* Provides linkage for the qmap container.
+*
+* rec
+* NodeRecord for this node as read from the database file.
+*
+* comp
+* NodeRecord indicating which fields should be compared against rec.
+* Bits set in the comp NodeRecord indicate that bit in the rec structure
+* should be compared against real-time data from the SA.
+*
+* count
+* Utility counter used by the validation logic. Typically used to
+* to indicate the number of times a matching node was received from
+* the SA.
+*
+* SEE ALSO
+*********/
+
+static inline node_t *
+node_new( void )
+{
+ node_t *p_obj;
+
+ p_obj = cl_zalloc( sizeof( *p_obj ) );
+ return ( p_obj );
+}
+
+static inline void
+node_delete( IN node_t * p_obj )
+{
+ cl_free( p_obj );
+}
+
+/****s* Subnet Database/port_t
+* NAME
+* port_t
+*
+* DESCRIPTION
+* Subnet database object for ports.
+* Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _port
+{
+ cl_map_item_t map_item; /* must be first element! */
+ uint32_t count; /* must be second element! */
+ /* Since there is no uniq identifier for all ports we
+ must be able to have such a key by the lid and port num */
+ uint64_t port_id;
+ ib_portinfo_record_t rec;
+ ib_portinfo_record_t comp;
+}
+port_t;
+
+/*
+* FIELDS
+*
+* map_item
+* Provides linkage for the qmap container.
+*
+* rec
+* PortInfoRecord for this port as read from the database file.
+*
+* comp
+* PortInfoRecord indicating which fields should be compared against rec.
+* Bits set in the comp NodeRecord indicate that bit in the rec structure
+* should be compared against real-time data from the SA.
+*
+* count
+* Utility counter used by the validation logic. Typically used to
+* to indicate the number of times a matching node was received from
+* the SA.
+*
+* SEE ALSO
+*********/
+
+static inline port_t *
+port_new( void )
+{
+ port_t *p_obj;
+
+ p_obj = cl_zalloc( sizeof( *p_obj ) );
+ return ( p_obj );
+}
+
+static inline void
+port_delete( IN port_t * p_obj )
+{
+ cl_free( p_obj );
+}
+
+
+static inline uint64_t
+port_gen_id(
+ IN ib_net16_t const lid,
+ IN uint8_t const port_num)
+{
+ return( lid << 8 | port_num );
+}
+
+static inline void
+port_ext_id( IN uint64_t id,
+ IN ib_net16_t *p_lid,
+ IN uint8_t *p_port_num)
+{
+ CL_ASSERT( (id & 0xFF) < 0x100 );
+ *p_port_num = (uint8_t)(id & 0xFF);
+ CL_ASSERT( ((id >> 8) & 0xFFFF) < 0x10000 );
+ *p_lid = (uint16_t)((id >> 8) & 0xFFFF);
+}
+
+static inline void
+port_set_id( IN port_t * p_obj,
+ IN ib_net16_t const lid,
+ IN uint8_t const port_num)
+{
+ p_obj->port_id = port_gen_id(lid, port_num);
+}
+
+static inline void
+port_get_id( IN port_t * p_obj,
+ IN ib_net16_t *p_lid,
+ IN uint8_t *p_port_num)
+{
+ port_ext_id(p_obj->port_id, p_lid, p_port_num);
+}
+
+/****s* Subnet Database/path_t
+* NAME
+* node_t
+*
+* DESCRIPTION
+* Subnet database object for paths.
+* Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _path
+{
+ cl_map_item_t map_item; /* must be first element! */
+ uint32_t count; /* must be second element! */
+ ib_path_rec_t rec;
+ ib_path_rec_t comp;
+
+}
+path_t;
+
+/*
+* FIELDS
+* map_item
+* Provides linkage for the qmap container.
+*
+* rec
+* PathRecord for this path as read from the database file.
+*
+* comp
+* PathRecord indicating which fields should be compared against rec.
+* Bits set in the comp PathRecord indicate that bit in the rec structure
+* should be compared against real-time data from the SA.
+*
+* count
+* Utility counter used by the validation logic. Typically used to
+* to indicate the number of times a matching node was received from
+* the SA.
+*
+* SEE ALSO
+*********/
+
+static inline path_t *
+path_new( void )
+{
+ path_t *p_obj;
+
+ p_obj = cl_zalloc( sizeof( *p_obj ) );
+ return ( p_obj );
+}
+
+static inline void
+path_delete( IN path_t * p_obj )
+{
+ cl_free( p_obj );
+}
+
+/****s* Subnet Database/subnet_t
+* NAME
+* subnet_t
+*
+* DESCRIPTION
+* Subnet database object.
+*
+* SYNOPSIS
+*/
+typedef struct _subnet
+{
+ cl_qmap_t node_lid_tbl;
+ cl_qmap_t node_guid_tbl;
+ cl_qmap_t mgrp_mlid_tbl;
+#if 0
+ cl_qmap_t port_lid_tbl;
+ cl_qmap_t port_guid_tbl;
+#endif
+ cl_qmap_t port_key_tbl;
+ cl_qmap_t link_tbl;
+ cl_qmap_t path_tbl;
+
+}
+subnet_t;
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****f* Subnet Database/subnet_init
+* NAME
+* subnet_init
+*
+* DESCRIPTION
+* This function constructs an subnet database object.
+* This function cannot fail.
+*
+* SYNOPSIS
+*/
+void subnet_construct( IN subnet_t * const p_subn );
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****f* Subnet Database/subnet_init
+* NAME
+* subnet_init
+*
+* DESCRIPTION
+* This function initializes an subnet database object.
+*
+* SYNOPSIS
+*/
+cl_status_t subnet_init( IN subnet_t * const p_subn );
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+#endif