From: eitan Date: Tue, 27 Sep 2005 07:59:33 +0000 (+0000) Subject: New opensm component X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=98eb30c5310c90dda888040f840046538ab128ec;p=~shefty%2Frdma-win.git New opensm component git-svn-id: svn://openib.tc.cornell.edu/gen1@99 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/dirs b/trunk/ulp/dirs index d41ec66e..75d677ac 100644 --- a/trunk/ulp/dirs +++ b/trunk/ulp/dirs @@ -1,5 +1,6 @@ DIRS=\ dapl \ ipoib \ - srp \ + srp \ + opensm \ wsd diff --git a/trunk/ulp/opensm/dirs b/trunk/ulp/opensm/dirs new file mode 100644 index 00000000..db5a8974 --- /dev/null +++ b/trunk/ulp/opensm/dirs @@ -0,0 +1,2 @@ +DIRS=\ + user diff --git a/trunk/ulp/opensm/user/dirs b/trunk/ulp/opensm/user/dirs new file mode 100644 index 00000000..d7822e5e --- /dev/null +++ b/trunk/ulp/opensm/user/dirs @@ -0,0 +1,7 @@ +DIRS=\ + libvendor \ + libopensm \ + opensm \ + osmtest \ + ibtrapgen + diff --git a/trunk/ulp/opensm/user/ibtrapgen/Makefile b/trunk/ulp/opensm/user/ibtrapgen/Makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/trunk/ulp/opensm/user/ibtrapgen/Makefile @@ -0,0 +1,7 @@ +# +# 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 diff --git a/trunk/ulp/opensm/user/ibtrapgen/SOURCES b/trunk/ulp/opensm/user/ibtrapgen/SOURCES new file mode 100644 index 00000000..54e5501c --- /dev/null +++ b/trunk/ulp/opensm/user/ibtrapgen/SOURCES @@ -0,0 +1,67 @@ +!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 + diff --git a/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c b/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c new file mode 100644 index 00000000..c6bd3a24 --- /dev/null +++ b/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c @@ -0,0 +1,442 @@ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 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 +#include +#include +#include +#include "ibtrapgen.h" +#include +#include +#include + +#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); +} diff --git a/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.h b/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.h new file mode 100644 index 00000000..6fe54862 --- /dev/null +++ b/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.h @@ -0,0 +1,313 @@ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 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 +#include +#include +#include +#include +#include + +/****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 /* */ diff --git a/trunk/ulp/opensm/user/ibtrapgen/main.c b/trunk/ulp/opensm/user/ibtrapgen/main.c new file mode 100644 index 00000000..bb23326c --- /dev/null +++ b/trunk/ulp/opensm/user/ibtrapgen/main.c @@ -0,0 +1,463 @@ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 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 +#include +#ifndef __WIN__ +#include +#endif +#include +#include +#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 -n|--number \n" + " -r|--rate -l|--lid \n" + " -s|--src_port -p|--port_num \n" ); + printf( "\nOptions:\n" ); + printf( "-t \n" + "--trap_num \n" + " This option specifies the number of the trap to generate.\n" + " Valid values are 128-131.\n" ); + printf( "-n \n" + "--number \n" + " This option specifies the number of times to generate this trap.\n" + " If not specified - default to 1.\n" ); + printf( "-r \n" + "--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 \n" + "--lid \n" + " This option specifies the lid address from where the trap should\n" + " be generated.\n" ); + printf( "-s \n" + "--src_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 \n" + "--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 \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 ); +} diff --git a/trunk/ulp/opensm/user/include/complib/cl_byteswap.h b/trunk/ulp/opensm/user/include/complib/cl_byteswap.h new file mode 100644 index 00000000..2ba5a771 --- /dev/null +++ b/trunk/ulp/opensm/user/include/complib/cl_byteswap.h @@ -0,0 +1,547 @@ +/* + * 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 +#include + + +/****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_ */ diff --git a/trunk/ulp/opensm/user/include/complib/cl_signal_osd.h b/trunk/ulp/opensm/user/include/complib/cl_signal_osd.h new file mode 100644 index 00000000..dedd99ae --- /dev/null +++ b/trunk/ulp/opensm/user/include/complib/cl_signal_osd.h @@ -0,0 +1,127 @@ +/* + * 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 + +/****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_ */ diff --git a/trunk/ulp/opensm/user/include/iba/ib_types.h b/trunk/ulp/opensm/user/include/iba/ib_types.h new file mode 100644 index 00000000..9bd0c189 --- /dev/null +++ b/trunk/ulp/opensm/user/include/iba/ib_types.h @@ -0,0 +1,9548 @@ +/* + * 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 +#include +#include + +#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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/************/ +/****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 +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 +/**********/ +#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 +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 + +#include +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 + +/****s* IBA Base: Types/ib_port_info_t +* NAME +* ib_port_info_t +* +* DESCRIPTION +* IBA defined PortInfo. (14.2.5.6) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +#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 +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 + +#include +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 + +#include +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 + +#include +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 + +/****s* IBA Base: Types/ib_lft_record_t +* NAME +* ib_lft_record_t +* +* DESCRIPTION +* IBA defined LinearForwardingTable. (14.2.5.6) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +/****s* IBA Base: Types/ib_switch_info_t +* NAME +* ib_switch_info_t +* +* DESCRIPTION +* IBA defined SwitchInfo. (14.2.5.4) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +#include +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 + +#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 +typedef struct _ib_guid_info +{ + ib_net64_t guid[GUID_TABLE_MAX_ENTRIES]; + +} PACK_SUFFIX ib_guid_info_t; +#include +/************/ + +#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 +typedef struct _ib_pkey_table +{ + ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK]; + +} PACK_SUFFIX ib_pkey_table_t; +#include +/************/ + +/****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 +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 +/************/ + +#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 +typedef struct _ib_slvl_table +{ + uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2]; +} PACK_SUFFIX ib_slvl_table_t; +#include +/************/ + +/****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 +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 +/************/ + +/****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 +typedef struct _ib_vl_arb_element +{ + uint8_t vl; + uint8_t weight; + +} PACK_SUFFIX ib_vl_arb_element_t; +#include +/************/ + +#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 +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 +/************/ + +/****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 +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 +/************/ + +/* + * Global route header information received with unreliable datagram messages + */ +#include +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 + +/****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 +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 +/* +* 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 +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 + +/****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 +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 + +/****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 +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 + +/****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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 +/* +* 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 +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 + +/* + * 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 +#endif + +#endif // __IB_TYPES_H__ diff --git a/trunk/ulp/opensm/user/include/iba/ib_types_extended.h b/trunk/ulp/opensm/user/include/iba/ib_types_extended.h new file mode 100644 index 00000000..3340c914 --- /dev/null +++ b/trunk/ulp/opensm/user/include/iba/ib_types_extended.h @@ -0,0 +1,2485 @@ +/* + * 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__ diff --git a/trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h b/trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h new file mode 100644 index 00000000..7b5a3ec1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h @@ -0,0 +1,673 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_) */ diff --git a/trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h b/trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h new file mode 100644 index 00000000..559f2aaa --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h @@ -0,0 +1,497 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_) */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h b/trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h new file mode 100644 index 00000000..c532c589 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h @@ -0,0 +1,117 @@ +/* + * 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 + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_base.h b/trunk/ulp/opensm/user/include/opensm/osm_base.h new file mode 100644 index 00000000..cafde5e7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_base.h @@ -0,0 +1,715 @@ +/* + * 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 +#define OSM_CDECL __cdecl +#else +#define OSM_CDECL +#endif + +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_base.h.orig b/trunk/ulp/opensm/user/include/opensm/osm_base.h.orig new file mode 100755 index 00000000..8e8a2d4f --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_base.h.orig @@ -0,0 +1,717 @@ +/* + * 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 +#define OSM_CDECL __cdecl +#else +#define OSM_CDECL +#endif + +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_db.h b/trunk/ulp/opensm/user/include/opensm/osm_db.h new file mode 100644 index 00000000..65286292 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_db.h @@ -0,0 +1,455 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_db_pack.h b/trunk/ulp/opensm/user/include/opensm/osm_db_pack.h new file mode 100644 index 00000000..4c382a45 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_db_pack.h @@ -0,0 +1,254 @@ +/* + * 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 + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h new file mode 100644 index 00000000..42d246ab --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h @@ -0,0 +1,258 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_errors.h b/trunk/ulp/opensm/user/include/opensm/osm_errors.h new file mode 100644 index 00000000..adcd33ef --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_errors.h @@ -0,0 +1,180 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h new file mode 100644 index 00000000..d42f36e2 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h @@ -0,0 +1,227 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h new file mode 100644 index 00000000..0045b21a --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h @@ -0,0 +1,388 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_helper.h b/trunk/ulp/opensm/user/include/opensm/osm_helper.h new file mode 100644 index 00000000..de351004 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_helper.h @@ -0,0 +1,592 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_inform.h b/trunk/ulp/opensm/user/include/opensm/osm_inform.h new file mode 100644 index 00000000..e8ad23fd --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_inform.h @@ -0,0 +1,325 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h new file mode 100644 index 00000000..7fe07c83 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h @@ -0,0 +1,319 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h new file mode 100644 index 00000000..9850a7f7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h @@ -0,0 +1,254 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h new file mode 100644 index 00000000..a62f5fcc --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h @@ -0,0 +1,232 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h new file mode 100644 index 00000000..7d3a6743 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h @@ -0,0 +1,374 @@ +/* + * 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 +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h new file mode 100644 index 00000000..76c9dc81 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h @@ -0,0 +1,271 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_log.h b/trunk/ulp/opensm/user/include/opensm/osm_log.h new file mode 100644 index 00000000..c84355f8 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_log.h @@ -0,0 +1,480 @@ +/* + * 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 +#endif +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h b/trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h new file mode 100644 index 00000000..1d55478d --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h @@ -0,0 +1,404 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_madw.h b/trunk/ulp/opensm/user/include/opensm/osm_madw.h new file mode 100644 index 00000000..3da00570 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_madw.h @@ -0,0 +1,1143 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_matrix.h b/trunk/ulp/opensm/user/include/opensm/osm_matrix.h new file mode 100644 index 00000000..98ea62ed --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_matrix.h @@ -0,0 +1,449 @@ +/* + * 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 +#include +#include + +#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 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h new file mode 100644 index 00000000..17390bac --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h @@ -0,0 +1,288 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h new file mode 100644 index 00000000..9b73e8c1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h @@ -0,0 +1,258 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h new file mode 100644 index 00000000..b9747fa9 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h @@ -0,0 +1,234 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h new file mode 100644 index 00000000..477bf921 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h @@ -0,0 +1,383 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h new file mode 100644 index 00000000..7588d9d6 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h @@ -0,0 +1,484 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h b/trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h new file mode 100644 index 00000000..fe7ca2ae --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h @@ -0,0 +1,235 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h b/trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h new file mode 100644 index 00000000..7a23240e --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h @@ -0,0 +1,267 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcmember.h b/trunk/ulp/opensm/user/include/opensm/osm_mcmember.h new file mode 100644 index 00000000..ab47ea2a --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mcmember.h @@ -0,0 +1,157 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_msgdef.h b/trunk/ulp/opensm/user/include/opensm/osm_msgdef.h new file mode 100644 index 00000000..665782e1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_msgdef.h @@ -0,0 +1,196 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h b/trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h new file mode 100644 index 00000000..c4247726 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h @@ -0,0 +1,142 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mtree.h b/trunk/ulp/opensm/user/include/opensm/osm_mtree.h new file mode 100644 index 00000000..77de6e97 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_mtree.h @@ -0,0 +1,378 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_multicast.h b/trunk/ulp/opensm/user/include/opensm/osm_multicast.h new file mode 100644 index 00000000..17962caa --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_multicast.h @@ -0,0 +1,769 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_node.h b/trunk/ulp/opensm/user/include/opensm/osm_node.h new file mode 100644 index 00000000..244edaf9 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_node.h @@ -0,0 +1,945 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h new file mode 100644 index 00000000..72cc1fe0 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h @@ -0,0 +1,255 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h new file mode 100644 index 00000000..d62991ab --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h new file mode 100644 index 00000000..d5e589dc --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h @@ -0,0 +1,305 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h new file mode 100644 index 00000000..d9c9cea0 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_opensm.h b/trunk/ulp/opensm/user/include/opensm/osm_opensm.h new file mode 100644 index 00000000..d3dce382 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_opensm.h @@ -0,0 +1,422 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_partition.h b/trunk/ulp/opensm/user/include/opensm/osm_partition.h new file mode 100644 index 00000000..b4e1ed66 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_partition.h @@ -0,0 +1,280 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_path.h b/trunk/ulp/opensm/user/include/opensm/osm_path.h new file mode 100644 index 00000000..21faf3b1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_path.h @@ -0,0 +1,264 @@ +/* + * 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 +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h new file mode 100644 index 00000000..ab5ea3a6 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h @@ -0,0 +1,286 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey.h new file mode 100644 index 00000000..b2d405a0 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_pkey.h @@ -0,0 +1,489 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h new file mode 100644 index 00000000..070399d7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h @@ -0,0 +1,286 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h new file mode 100644 index 00000000..b97987af --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h @@ -0,0 +1,253 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h new file mode 100644 index 00000000..459c1b85 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h @@ -0,0 +1,248 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_port.h b/trunk/ulp/opensm/user/include/opensm/osm_port.h new file mode 100644 index 00000000..21cf041a --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_port.h @@ -0,0 +1,1980 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h new file mode 100644 index 00000000..c2e0b21a --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h @@ -0,0 +1,275 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h new file mode 100644 index 00000000..dd0c1e40 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_port_profile.h b/trunk/ulp/opensm/user/include/opensm/osm_port_profile.h new file mode 100644 index 00000000..de208502 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_port_profile.h @@ -0,0 +1,287 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h new file mode 100644 index 00000000..74130c74 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h @@ -0,0 +1,348 @@ +/* + * 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 +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h b/trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h new file mode 100644 index 00000000..8ce22a9e --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h @@ -0,0 +1,215 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_req.h b/trunk/ulp/opensm/user/include/opensm/osm_req.h new file mode 100644 index 00000000..72e4ff00 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_req.h @@ -0,0 +1,350 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h new file mode 100644 index 00000000..960143b7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h @@ -0,0 +1,229 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_resp.h b/trunk/ulp/opensm/user/include/opensm/osm_resp.h new file mode 100644 index 00000000..3d3c107c --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_resp.h @@ -0,0 +1,278 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa.h b/trunk/ulp/opensm/user/include/opensm/osm_sa.h new file mode 100644 index 00000000..afd79c9c --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa.h @@ -0,0 +1,524 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h new file mode 100644 index 00000000..6ea19295 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h @@ -0,0 +1,269 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h new file mode 100644 index 00000000..2a558b32 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h new file mode 100644 index 00000000..f8d6be86 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h @@ -0,0 +1,265 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h new file mode 100644 index 00000000..69873f70 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h new file mode 100644 index 00000000..83047f26 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h @@ -0,0 +1,262 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h new file mode 100644 index 00000000..5ca80cb1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h @@ -0,0 +1,234 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h new file mode 100644 index 00000000..694e28c3 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h @@ -0,0 +1,277 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h new file mode 100644 index 00000000..60615f88 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h new file mode 100644 index 00000000..8107b2e1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h @@ -0,0 +1,352 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h new file mode 100644 index 00000000..af2d1bf0 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h @@ -0,0 +1,363 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h new file mode 100644 index 00000000..b295c435 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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 */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h new file mode 100644 index 00000000..5d41ed22 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h @@ -0,0 +1,274 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h new file mode 100644 index 00000000..2da33ee7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h new file mode 100644 index 00000000..23f65fdc --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h @@ -0,0 +1,275 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h new file mode 100644 index 00000000..4e18ff47 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h new file mode 100644 index 00000000..89362e8d --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h @@ -0,0 +1,268 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h new file mode 100644 index 00000000..b71f33a1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h @@ -0,0 +1,218 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h new file mode 100644 index 00000000..89ad79c1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h @@ -0,0 +1,281 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h new file mode 100644 index 00000000..81bea3be --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_response.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_response.h new file mode 100644 index 00000000..a7c23694 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_response.h @@ -0,0 +1,256 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h new file mode 100644 index 00000000..a5ca56ea --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h @@ -0,0 +1,298 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h new file mode 100644 index 00000000..464a28ee --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h @@ -0,0 +1,230 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h new file mode 100644 index 00000000..9a5de461 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h @@ -0,0 +1,281 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h new file mode 100644 index 00000000..0acfc624 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h new file mode 100644 index 00000000..d67977da --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h @@ -0,0 +1,274 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h new file mode 100644 index 00000000..fd3cd5ea --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h new file mode 100644 index 00000000..3522d152 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h @@ -0,0 +1,281 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h new file mode 100644 index 00000000..4698e378 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_service.h b/trunk/ulp/opensm/user/include/opensm/osm_service.h new file mode 100644 index 00000000..dde23691 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_service.h @@ -0,0 +1,242 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h new file mode 100644 index 00000000..fddfaae7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h @@ -0,0 +1,265 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h new file mode 100644 index 00000000..29bfeecc --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm.h b/trunk/ulp/opensm/user/include/opensm/osm_sm.h new file mode 100644 index 00000000..78efd12f --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sm.h @@ -0,0 +1,567 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h new file mode 100644 index 00000000..52a43ce6 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h @@ -0,0 +1,294 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h new file mode 100644 index 00000000..3cf6bac2 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h @@ -0,0 +1,340 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h new file mode 100644 index 00000000..bde34046 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h @@ -0,0 +1,352 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h new file mode 100644 index 00000000..d8cf2182 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h @@ -0,0 +1,290 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h new file mode 100644 index 00000000..1a438da8 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h new file mode 100644 index 00000000..0d836072 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h @@ -0,0 +1,527 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h new file mode 100644 index 00000000..ad49a8e7 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h @@ -0,0 +1,233 @@ +/* + * 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 +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_stats.h b/trunk/ulp/opensm/user/include/opensm/osm_stats.h new file mode 100644 index 00000000..944b9bf1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_stats.h @@ -0,0 +1,123 @@ +/* + * 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 +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_subnet.h b/trunk/ulp/opensm/user/include/opensm/osm_subnet.h new file mode 100644 index 00000000..4e0793d8 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_subnet.h @@ -0,0 +1,1018 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h new file mode 100644 index 00000000..18fddb8c --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h @@ -0,0 +1,287 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h new file mode 100644 index 00000000..ff238d04 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h @@ -0,0 +1,303 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h new file mode 100644 index 00000000..f282d16f --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h new file mode 100644 index 00000000..0f515b22 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h @@ -0,0 +1,239 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_switch.h b/trunk/ulp/opensm/user/include/opensm/osm_switch.h new file mode 100644 index 00000000..320a45b9 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_switch.h @@ -0,0 +1,1455 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h new file mode 100644 index 00000000..5a3945f1 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h @@ -0,0 +1,325 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h new file mode 100644 index 00000000..483d13f8 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h b/trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h new file mode 100644 index 00000000..fb2febaf --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h @@ -0,0 +1,52 @@ +/* + * 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 + diff --git a/trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h new file mode 100644 index 00000000..af86f2ae --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h @@ -0,0 +1,273 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h b/trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h new file mode 100644 index 00000000..b82582e4 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h @@ -0,0 +1,472 @@ +/* + * 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 +#include +#include +#include +#include +#include +*/ + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_umadt.h b/trunk/ulp/opensm/user/include/opensm/osm_umadt.h new file mode 100644 index 00000000..3285cebe --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_umadt.h @@ -0,0 +1,142 @@ +/* + * 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 +#include +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h b/trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h new file mode 100644 index 00000000..2c07ed3a --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h @@ -0,0 +1,390 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h new file mode 100644 index 00000000..d9573420 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h @@ -0,0 +1,265 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h new file mode 100644 index 00000000..dc913433 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/opensm/st.h b/trunk/ulp/opensm/user/include/opensm/st.h new file mode 100644 index 00000000..2e532980 --- /dev/null +++ b/trunk/ulp/opensm/user/include/opensm/st.h @@ -0,0 +1,104 @@ +/* + * 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 */ diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor.h new file mode 100644 index 00000000..21baaee6 --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/osm_vendor.h @@ -0,0 +1,76 @@ +/* + * 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 + +#if defined( OSM_VENDOR_INTF_TEST ) +#include +#elif defined( OSM_VENDOR_INTF_UMADT ) +#include +#elif defined( OSM_VENDOR_INTF_MTL ) +/* HACK - I do not know how to prevent complib from loading kernel H files */ +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_TS ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_ANAFA ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_SIM ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_OPENIB ) +#include +#elif defined( OSM_VENDOR_INTF_AL ) +#include +#elif +#error No MAD Interface selected! +#error Choose an interface in osm_vendor_select.h +#endif + diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h new file mode 100644 index 00000000..44b90863 --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h @@ -0,0 +1,371 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h new file mode 100644 index 00000000..f37b386a --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h @@ -0,0 +1,528 @@ +/* + * 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 +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h new file mode 100644 index 00000000..5c4cd9c5 --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h @@ -0,0 +1,775 @@ +/* + * 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 + +#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_ */ diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h new file mode 100644 index 00000000..9f534586 --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h @@ -0,0 +1,74 @@ +/* + * 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_ */ diff --git a/trunk/ulp/opensm/user/include/vendor/winosm_common.h b/trunk/ulp/opensm/user/include/vendor/winosm_common.h new file mode 100644 index 00000000..da538ce2 --- /dev/null +++ b/trunk/ulp/opensm/user/include/vendor/winosm_common.h @@ -0,0 +1,221 @@ +#ifndef _OSM_COMMON_H_ +#define _OSM_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/trunk/ulp/opensm/user/libopensm/Makefile b/trunk/ulp/opensm/user/libopensm/Makefile new file mode 100755 index 00000000..58189757 --- /dev/null +++ b/trunk/ulp/opensm/user/libopensm/Makefile @@ -0,0 +1,7 @@ +# +# 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 diff --git a/trunk/ulp/opensm/user/libopensm/SOURCES b/trunk/ulp/opensm/user/libopensm/SOURCES new file mode 100644 index 00000000..370e2bcb --- /dev/null +++ b/trunk/ulp/opensm/user/libopensm/SOURCES @@ -0,0 +1,63 @@ +!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 diff --git a/trunk/ulp/opensm/user/libopensm/osm_helper.c b/trunk/ulp/opensm/user/libopensm/osm_helper.c new file mode 100644 index 00000000..67008051 --- /dev/null +++ b/trunk/ulp/opensm/user/libopensm/osm_helper.c @@ -0,0 +1,2006 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#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] ); +} + diff --git a/trunk/ulp/opensm/user/libopensm/osm_log.c b/trunk/ulp/opensm/user/libopensm/osm_log.c new file mode 100644 index 00000000..113d9671 --- /dev/null +++ b/trunk/ulp/opensm/user/libopensm/osm_log.c @@ -0,0 +1,221 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include + +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_ ) */ +} diff --git a/trunk/ulp/opensm/user/libopensm/osm_mad_pool.c b/trunk/ulp/opensm/user/libopensm/osm_mad_pool.c new file mode 100644 index 00000000..a260adea --- /dev/null +++ b/trunk/ulp/opensm/user/libopensm/osm_mad_pool.c @@ -0,0 +1,300 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#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 ); +} + diff --git a/trunk/ulp/opensm/user/libvendor/Makefile b/trunk/ulp/opensm/user/libvendor/Makefile new file mode 100644 index 00000000..58189757 --- /dev/null +++ b/trunk/ulp/opensm/user/libvendor/Makefile @@ -0,0 +1,7 @@ +# +# 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 diff --git a/trunk/ulp/opensm/user/libvendor/SOURCES b/trunk/ulp/opensm/user/libvendor/SOURCES new file mode 100644 index 00000000..d128cdfd --- /dev/null +++ b/trunk/ulp/opensm/user/libvendor/SOURCES @@ -0,0 +1,61 @@ +!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 diff --git a/trunk/ulp/opensm/user/libvendor/osm_vendor_al.c b/trunk/ulp/opensm/user/libvendor/osm_vendor_al.c new file mode 100644 index 00000000..6ac713f9 --- /dev/null +++ b/trunk/ulp/opensm/user/libvendor/osm_vendor_al.c @@ -0,0 +1,1593 @@ +/* + * 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 + +#ifdef OSM_VENDOR_INTF_AL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****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 */ diff --git a/trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c b/trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c new file mode 100644 index 00000000..f53685db --- /dev/null +++ b/trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c @@ -0,0 +1,854 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + + +/***************************************************************************** + *****************************************************************************/ + +/* 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_nump_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; +} + + +/***************************************************************************** + *****************************************************************************/ + + diff --git a/trunk/ulp/opensm/user/libvendor/winosm_common.c b/trunk/ulp/opensm/user/libvendor/winosm_common.c new file mode 100644 index 00000000..9523beab --- /dev/null +++ b/trunk/ulp/opensm/user/libvendor/winosm_common.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include + +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; +} + + +/******************************************************************************/ diff --git a/trunk/ulp/opensm/user/opensm/Makefile b/trunk/ulp/opensm/user/opensm/Makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/Makefile @@ -0,0 +1,7 @@ +# +# 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 diff --git a/trunk/ulp/opensm/user/opensm/SOURCES b/trunk/ulp/opensm/user/opensm/SOURCES new file mode 100644 index 00000000..66a0bedf --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/SOURCES @@ -0,0 +1,153 @@ +!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 diff --git a/trunk/ulp/opensm/user/opensm/cl_dispatcher.c b/trunk/ulp/opensm/user/opensm/cl_dispatcher.c new file mode 100644 index 00000000..2e3242d1 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/cl_dispatcher.c @@ -0,0 +1,409 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/* 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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/cl_event_wheel.c b/trunk/ulp/opensm/user/opensm/cl_event_wheel.c new file mode 100644 index 00000000..e23d51c2 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/cl_event_wheel.c @@ -0,0 +1,660 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +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__ */ diff --git a/trunk/ulp/opensm/user/opensm/main.c b/trunk/ulp/opensm/user/opensm/main.c new file mode 100644 index 00000000..a5b46512 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/main.c @@ -0,0 +1,788 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include "stdio.h" +#include +#include +#include +#include +#include +#include + +/******************************************************************** + 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 \n" + "--guid \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 \n" + "--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 \n" + "--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 \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 \n" + "--sweep \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 \n" + "--timeout \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 \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 \n" + "-ignore-guids \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 \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 \n" + "--debug \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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/opensm.rc b/trunk/ulp/opensm/user/opensm/opensm.rc new file mode 100644 index 00000000..588b227a --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/opensm.rc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. 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 + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN +#ifdef _DEBUG_ +#define VER_FILEDESCRIPTION_STR "Debug OpenSM Subnet Manager Application" +#define VER_INTERNALNAME_STR "opensm.exe" +#define VER_ORIGINALFILENAME_STR "opensm.exe" +#else +#define VER_FILEDESCRIPTION_STR "OpenSM Subnet Manager Application" +#define VER_INTERNALNAME_STR "opensm.exe" +#define VER_ORIGINALFILENAME_STR "opensm.exe" +#endif +#include diff --git a/trunk/ulp/opensm/user/opensm/osm_db_files.c b/trunk/ulp/opensm/user/opensm/osm_db_files.c new file mode 100644 index 00000000..2d964691 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_db_files.c @@ -0,0 +1,769 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +/****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 +#include + +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 diff --git a/trunk/ulp/opensm/user/opensm/osm_db_pack.c b/trunk/ulp/opensm/user/opensm/osm_db_pack.c new file mode 100644 index 00000000..9d6df773 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_db_pack.c @@ -0,0 +1,168 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +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) ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_drop_mgr.c b/trunk/ulp/opensm/user/opensm/osm_drop_mgr.c new file mode 100644 index 00000000..1e75ef5f --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_drop_mgr.c @@ -0,0 +1,722 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c b/trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c new file mode 100644 index 00000000..6edfad63 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c @@ -0,0 +1,113 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +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 ); + } +} diff --git a/trunk/ulp/opensm/user/opensm/osm_inform.c b/trunk/ulp/opensm/user/opensm/osm_inform.c new file mode 100644 index 00000000..655e9691 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_inform.c @@ -0,0 +1,718 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_lid_mgr.c b/trunk/ulp/opensm/user/opensm/osm_lid_mgr.c new file mode 100644 index 00000000..f4c25f72 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_lid_mgr.c @@ -0,0 +1,1316 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + 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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c new file mode 100644 index 00000000..b725b2b3 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c @@ -0,0 +1,161 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c new file mode 100644 index 00000000..ea3322bf --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c @@ -0,0 +1,124 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c new file mode 100644 index 00000000..75e94d2d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c @@ -0,0 +1,99 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + + +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; +} diff --git a/trunk/ulp/opensm/user/opensm/osm_link_mgr.c b/trunk/ulp/opensm/user/opensm/osm_link_mgr.c new file mode 100644 index 00000000..469c5916 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_link_mgr.c @@ -0,0 +1,476 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_matrix.c b/trunk/ulp/opensm/user/opensm/osm_matrix.c new file mode 100644 index 00000000..3c3dc485 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_matrix.c @@ -0,0 +1,153 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include + + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c new file mode 100644 index 00000000..6c0a519c --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c @@ -0,0 +1,180 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c new file mode 100644 index 00000000..078c16d2 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c @@ -0,0 +1,125 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c b/trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c new file mode 100644 index 00000000..b152fc3e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c @@ -0,0 +1,1707 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + +} diff --git a/trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c b/trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c new file mode 100644 index 00000000..fe388718 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c @@ -0,0 +1,298 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_mcm_info.c b/trunk/ulp/opensm/user/opensm/osm_mcm_info.c new file mode 100644 index 00000000..aff3831e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcm_info.c @@ -0,0 +1,99 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_mcm_port.c b/trunk/ulp/opensm/user/opensm/osm_mcm_port.c new file mode 100644 index 00000000..edbf1c8d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mcm_port.c @@ -0,0 +1,123 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_mtree.c b/trunk/ulp/opensm/user/opensm/osm_mtree.c new file mode 100644 index 00000000..cdfa46dd --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_mtree.c @@ -0,0 +1,132 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include + +/********************************************************************** + **********************************************************************/ +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]); + } + } + +} diff --git a/trunk/ulp/opensm/user/opensm/osm_multicast.c b/trunk/ulp/opensm/user/opensm/osm_multicast.c new file mode 100644 index 00000000..d07046f4 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_multicast.c @@ -0,0 +1,402 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +/* 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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_node.c b/trunk/ulp/opensm/user/opensm/osm_node.c new file mode 100644 index 00000000..250aac4b --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_node.c @@ -0,0 +1,329 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c new file mode 100644 index 00000000..e502222b --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c @@ -0,0 +1,183 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c new file mode 100644 index 00000000..e52b0d87 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c @@ -0,0 +1,136 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c new file mode 100755 index 00000000..afe72a4e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c @@ -0,0 +1,1044 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************** + 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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c new file mode 100644 index 00000000..eeecc475 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c @@ -0,0 +1,136 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_opensm.c b/trunk/ulp/opensm/user/opensm/osm_opensm.c new file mode 100644 index 00000000..2e800d18 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_opensm.c @@ -0,0 +1,324 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_pkey.c b/trunk/ulp/opensm/user/opensm/osm_pkey.c new file mode 100644 index 00000000..c1dc8aa9 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_pkey.c @@ -0,0 +1,397 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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; +} diff --git a/trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c new file mode 100644 index 00000000..2cea8189 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c @@ -0,0 +1,222 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c new file mode 100644 index 00000000..233d527d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c @@ -0,0 +1,119 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_port.c b/trunk/ulp/opensm/user/opensm/osm_port.c new file mode 100644 index 00000000..98154c2e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_port.c @@ -0,0 +1,895 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c new file mode 100644 index 00000000..f11a3a71 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c @@ -0,0 +1,812 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c new file mode 100644 index 00000000..5aaba07a --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c @@ -0,0 +1,136 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_remote_sm.c b/trunk/ulp/opensm/user/opensm/osm_remote_sm.c new file mode 100644 index 00000000..534b4394 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_remote_sm.c @@ -0,0 +1,92 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_req.c b/trunk/ulp/opensm/user/opensm/osm_req.c new file mode 100644 index 00000000..908bb9f8 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_req.c @@ -0,0 +1,298 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_req_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_req_ctrl.c new file mode 100644 index 00000000..c5708822 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_req_ctrl.c @@ -0,0 +1,139 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_resp.c b/trunk/ulp/opensm/user/opensm/osm_resp.c new file mode 100644 index 00000000..2f50055c --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_resp.c @@ -0,0 +1,218 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa.c b/trunk/ulp/opensm/user/opensm/osm_sa.c new file mode 100644 index 00000000..3c62aa37 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa.c @@ -0,0 +1,589 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); + + } + +} + +/********************************************************************** + **********************************************************************/ + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c new file mode 100644 index 00000000..4454afa8 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c @@ -0,0 +1,260 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c new file mode 100644 index 00000000..126cd3c2 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c @@ -0,0 +1,130 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c new file mode 100644 index 00000000..246c21a2 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c @@ -0,0 +1,567 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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; +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c new file mode 100644 index 00000000..b2cc8185 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c @@ -0,0 +1,129 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c new file mode 100644 index 00000000..ed3894ee --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c @@ -0,0 +1,516 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c new file mode 100644 index 00000000..e60dd05a --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c @@ -0,0 +1,128 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_link_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_link_record.c new file mode 100644 index 00000000..8c6827bd --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_link_record.c @@ -0,0 +1,813 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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<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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c new file mode 100644 index 00000000..05706a60 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c @@ -0,0 +1,126 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c new file mode 100644 index 00000000..278e5cea --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c @@ -0,0 +1,627 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/****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 ); + +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c new file mode 100644 index 00000000..5d729410 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c @@ -0,0 +1,2251 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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||< P_Key >|00.......0|| + * +--------+----+----+-----------------+---------+----------+---------+ + * + * For IPv6 over IB, the signature will be "0x601B". + * + * | 8 | 4 | 4 | 16 bits | 16 bits | 80 bits | + * +--------+----+----+-----------------+---------+--------------------+ + * |11111111|0001|scop||< 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; + +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c new file mode 100644 index 00000000..7102a8bb --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c @@ -0,0 +1,132 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_node_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_node_record.c new file mode 100644 index 00000000..e8a21edc --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_node_record.c @@ -0,0 +1,618 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c new file mode 100644 index 00000000..a70e6b53 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c @@ -0,0 +1,124 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_path_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_path_record.c new file mode 100644 index 00000000..d75c1f9d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_path_record.c @@ -0,0 +1,1765 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c new file mode 100644 index 00000000..e5f9d8ee --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c @@ -0,0 +1,130 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c new file mode 100644 index 00000000..bbd7bb3e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c @@ -0,0 +1,587 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c new file mode 100644 index 00000000..9b0313d3 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c @@ -0,0 +1,117 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c new file mode 100644 index 00000000..d113eac4 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c @@ -0,0 +1,794 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c new file mode 100644 index 00000000..2d0657a5 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c @@ -0,0 +1,128 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_response.c b/trunk/ulp/opensm/user/opensm/osm_sa_response.c new file mode 100644 index 00000000..eacf399a --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_response.c @@ -0,0 +1,172 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_service_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_service_record.c new file mode 100644 index 00000000..fb95d255 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_service_record.c @@ -0,0 +1,1218 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); + +} + +/********************************************************************** + **********************************************************************/ + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c new file mode 100644 index 00000000..110fdf31 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c @@ -0,0 +1,126 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c new file mode 100644 index 00000000..8b6d0613 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c @@ -0,0 +1,551 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c new file mode 100644 index 00000000..7cc78c9a --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c @@ -0,0 +1,129 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c new file mode 100644 index 00000000..89924a1e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c @@ -0,0 +1,245 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c new file mode 100644 index 00000000..43115524 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c @@ -0,0 +1,128 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c new file mode 100644 index 00000000..4dc4e45c --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c @@ -0,0 +1,573 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c new file mode 100644 index 00000000..c8a9800e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c @@ -0,0 +1,129 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_service.c b/trunk/ulp/opensm/user/opensm/osm_service.c new file mode 100644 index 00000000..4daaecc9 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_service.c @@ -0,0 +1,206 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ + +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c new file mode 100644 index 00000000..dde027d8 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c @@ -0,0 +1,231 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c new file mode 100644 index 00000000..c495834f --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c @@ -0,0 +1,131 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sm.c b/trunk/ulp/opensm/user/opensm/osm_sm.c new file mode 100644 index 00000000..48eb00b7 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sm.c @@ -0,0 +1,844 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c new file mode 100644 index 00000000..f15836b1 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c @@ -0,0 +1,1061 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c b/trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c new file mode 100644 index 00000000..7537ea4d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c @@ -0,0 +1,862 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c new file mode 100755 index 00000000..eba36bda --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c @@ -0,0 +1,778 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c new file mode 100644 index 00000000..cd6db17e --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c @@ -0,0 +1,131 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_state_mgr.c b/trunk/ulp/opensm/user/opensm/osm_state_mgr.c new file mode 100644 index 00000000..df29764d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_state_mgr.c @@ -0,0 +1,2931 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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; +} diff --git a/trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c new file mode 100644 index 00000000..d20ee8b8 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c @@ -0,0 +1,136 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_subnet.c b/trunk/ulp/opensm/user/opensm/osm_subnet.c new file mode 100644 index 00000000..9ab35f79 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_subnet.c @@ -0,0 +1,938 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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^\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^\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^\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); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c new file mode 100644 index 00000000..5ac945df --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c @@ -0,0 +1,719 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c new file mode 100644 index 00000000..04132ff6 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c @@ -0,0 +1,136 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + + + + + + diff --git a/trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c new file mode 100644 index 00000000..fa2d09ca --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c @@ -0,0 +1,131 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_switch.c b/trunk/ulp/opensm/user/opensm/osm_switch.c new file mode 100644 index 00000000..489a4e6f --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_switch.c @@ -0,0 +1,544 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_trap_rcv.c b/trunk/ulp/opensm/user/opensm/osm_trap_rcv.c new file mode 100644 index 00000000..7dd44d1d --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_trap_rcv.c @@ -0,0 +1,735 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + * + * 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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c new file mode 100644 index 00000000..2cd19e96 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c @@ -0,0 +1,125 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c b/trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c new file mode 100644 index 00000000..796eb940 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c @@ -0,0 +1,1171 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_ucast_updn.c b/trunk/ulp/opensm/user/opensm/osm_ucast_updn.c new file mode 100644 index 00000000..3d604f3c --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_ucast_updn.c @@ -0,0 +1,1206 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + + +/* ///////////////////////////////// */ +/* 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; +} diff --git a/trunk/ulp/opensm/user/opensm/osm_vl15intf.c b/trunk/ulp/opensm/user/opensm/osm_vl15intf.c new file mode 100644 index 00000000..1b9aa205 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_vl15intf.c @@ -0,0 +1,463 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +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 ); +} diff --git a/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c new file mode 100644 index 00000000..1a541501 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c @@ -0,0 +1,239 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c new file mode 100644 index 00000000..8f0d97d6 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c @@ -0,0 +1,131 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +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 ); +} + diff --git a/trunk/ulp/opensm/user/opensm/st.c b/trunk/ulp/opensm/user/opensm/st.c new file mode 100644 index 00000000..a214eae2 --- /dev/null +++ b/trunk/ulp/opensm/user/opensm/st.c @@ -0,0 +1,626 @@ +/* + * 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 +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#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< size) return 1< 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; +} diff --git a/trunk/ulp/opensm/user/osmtest/Makefile b/trunk/ulp/opensm/user/osmtest/Makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/Makefile @@ -0,0 +1,7 @@ +# +# 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 diff --git a/trunk/ulp/opensm/user/osmtest/SOURCES b/trunk/ulp/opensm/user/osmtest/SOURCES new file mode 100644 index 00000000..b2a4ff37 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/SOURCES @@ -0,0 +1,71 @@ +!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 + diff --git a/trunk/ulp/opensm/user/osmtest/error.h b/trunk/ulp/opensm/user/osmtest/error.h new file mode 100644 index 00000000..11e25593 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/error.h @@ -0,0 +1,56 @@ +/* + * 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 + +*/ diff --git a/trunk/ulp/opensm/user/osmtest/main.c b/trunk/ulp/opensm/user/osmtest/main.c new file mode 100644 index 00000000..6f7affb7 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/main.c @@ -0,0 +1,543 @@ +/* + * 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 +#include +#ifndef __WIN__ +#include +#endif +#include +#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 \n" + "--flow \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 \n" + "--wait \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 \n" + "--debug \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 \n" + "--max_lid \n" + " This option specifies the maximal LID number to be searched\n" + " for during inventory file build (default to 100).\n"); + printf( "-g \n" + "--guid \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 \n" + "--inventory \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 \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 \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 ); +} diff --git a/trunk/ulp/opensm/user/osmtest/osmt_inform.c b/trunk/ulp/opensm/user/osmtest/osmt_inform.c new file mode 100644 index 00000000..98414032 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_inform.c @@ -0,0 +1,964 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#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 */ + diff --git a/trunk/ulp/opensm/user/osmtest/osmt_inform.h b/trunk/ulp/opensm/user/osmtest/osmt_inform.h new file mode 100644 index 00000000..866641bb --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_inform.h @@ -0,0 +1,80 @@ +/* + * 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 +#include +#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__ diff --git a/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c new file mode 100644 index 00000000..06347d98 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c @@ -0,0 +1,461 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +/* + * 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 */ diff --git a/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h new file mode 100644 index 00000000..56afd0b7 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h @@ -0,0 +1,199 @@ +/* + * 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 +#include +#include +#include + + +#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 diff --git a/trunk/ulp/opensm/user/osmtest/osmt_multicast.c b/trunk/ulp/opensm/user/osmtest/osmt_multicast.c new file mode 100644 index 00000000..c0ebdeff --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_multicast.c @@ -0,0 +1,3246 @@ +/* + * 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 +#endif +#include +#include +#include +#include +#include +#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; +} diff --git a/trunk/ulp/opensm/user/osmtest/osmt_service.c b/trunk/ulp/opensm/user/osmtest/osmt_service.c new file mode 100644 index 00000000..1c4a3f14 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_service.c @@ -0,0 +1,1597 @@ +/* + * 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 +#endif +#include +#include +#include +#include +#include +#include +#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 ; jlog, 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; +} + diff --git a/trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c b/trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c new file mode 100644 index 00000000..89707c22 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c @@ -0,0 +1,543 @@ +/* + * 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 +#include +#include +#include +#include +#include +#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 */ + diff --git a/trunk/ulp/opensm/user/osmtest/osmtest.c b/trunk/ulp/opensm/user/osmtest/osmtest.c new file mode 100644 index 00000000..b88cf79b --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmtest.c @@ -0,0 +1,6272 @@ +/* + * 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 +#include +#include +#include +#include +#include "osmtest.h" +#include + + +#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 ); +} diff --git a/trunk/ulp/opensm/user/osmtest/osmtest.h b/trunk/ulp/opensm/user/osmtest/osmtest.h new file mode 100644 index 00000000..005f0e28 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmtest.h @@ -0,0 +1,519 @@ +/* + * 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 +#include +#include +#include "osmtest_base.h" +#include "osmtest_subnet.h" +#include +#include +#include + +/****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_ */ diff --git a/trunk/ulp/opensm/user/osmtest/osmtest_base.h b/trunk/ulp/opensm/user/osmtest/osmtest_base.h new file mode 100644 index 00000000..c2874197 --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmtest_base.h @@ -0,0 +1,70 @@ +/* + * 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 +#else +#include +#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_ */ diff --git a/trunk/ulp/opensm/user/osmtest/osmtest_subnet.h b/trunk/ulp/opensm/user/osmtest/osmtest_subnet.h new file mode 100644 index 00000000..1bb7e89e --- /dev/null +++ b/trunk/ulp/opensm/user/osmtest/osmtest_subnet.h @@ -0,0 +1,354 @@ +/* + * 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 +#include +#include +#include +#include + + +/****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