[openib-general] [PATCH 2/4} OpenSM: Add optional SA MFTRecord support
Hal Rosenstock
halr at voltaire.com
Fri Dec 29 09:11:16 PST 2006
OpenSM: Add optional SA MFTRecord support
Signed-off-by: Hal Rosenstock <halr at voltaire.com>
diff --git a/osm/include/opensm/osm_sa_mft_record.h b/osm/include/opensm/osm_sa_mft_record.h
new file mode 100644
index 0000000..f961206
--- /dev/null
+++ b/osm/include/opensm/osm_sa_mft_record.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 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.
+ *
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_mftr_rcv_t.
+ * This object represents the MulticastForwardingTable Receiver object.
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_H_
+#define _OSM_MFTR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Forwarding Table Receiver
+* NAME
+* Multicast Forwarding Table Receiver
+*
+* DESCRIPTION
+* The Multicast Forwarding Table Receiver object encapsulates the information
+* needed to receive the MulticastForwardingTable attribute from a switch node.
+*
+* The Multicast Forwarding Table Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_t
+* NAME
+* osm_mftr_rcv_t
+*
+* DESCRIPTION
+* Multicast Forwarding Table Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft
+{
+ 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_mftr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the statistics.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* 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 Multicast Forwarding Table Record objects used to
+* generate the query response.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_construct
+* NAME
+* osm_mftr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_construct(
+ IN osm_mftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Multicast Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mftr_rcv_init, osm_mftr_rcv_destroy
+*
+* Calling osm_mftr_rcv_construct is a prerequisite to calling any other
+* method except osm_mftr_rcv_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_init,
+* osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_destroy
+* NAME
+* osm_mftr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mftr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_destroy(
+ IN osm_mftr_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
+* Multicast 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_mftr_rcv_construct or osm_mftr_rcv_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct,
+* osm_mftr_rcv_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_init
+* NAME
+* osm_mftr_rcv_init
+*
+* DESCRIPTION
+* The osm_mftr_rcv_init function initializes a
+* Multicast Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_init(
+ IN osm_mftr_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_mftr_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 Multicast Forwarding Table Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Multicast Forwarding Table Receiver methods.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct,
+* osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_process
+* NAME
+* osm_mftr_rcv_process
+*
+* DESCRIPTION
+* Process the MulticastForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_process(
+ IN osm_mftr_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mftr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the switch node's MulticastForwardingTable attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MulticastForwardingTable processing was successful.
+*
+* NOTES
+* This function processes a MulticastForwardingTable attribute.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver, Multicast Forwarding Table Response
+* Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_H_ */
diff --git a/osm/include/opensm/osm_sa_mft_record_ctrl.h b/osm/include/opensm/osm_sa_mft_record_ctrl.h
new file mode 100644
index 0000000..a28374d
--- /dev/null
+++ b/osm/include/opensm/osm_sa_mft_record_ctrl.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 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.
+ *
+ */
+
+/*
+ * Abstract:
+ * Declaration of osm_mftr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * MulticastForwardingTable attribute from a switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_RCV_CTRL_H_
+#define _OSM_MFTR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mft_record.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Forwarding Table Receive Controller
+* NAME
+* Multicast Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+* The Multicast Forwarding Table Receive Controller object encapsulates
+* the information needed to receive the MulticastFowardingTable attribute
+* from a switch node.
+*
+* The Multicast Forwarding Table Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_t
+* NAME
+* osm_mftr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Multicast 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_mftr_rcv_ctrl
+{
+ osm_mftr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+} osm_mftr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Multicast 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
+* Multicast Forwarding Table Receive Controller object
+* Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_construct
+* NAME
+* osm_mftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Forwarding Table Receive
+* Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_construct(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Multicast Forwarding Table Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mftr_rcv_ctrl_init, osm_mftr_rcv_ctrl_destroy
+*
+* Calling osm_mftr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_init,
+* osm_mftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_destroy
+* NAME
+* osm_mftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mftr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_destroy(
+ IN osm_mftr_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
+* Multicast 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_mftr_rcv_ctrl_construct or osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_construct,
+* osm_mftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_init
+* NAME
+* osm_mftr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mftr_rcv_ctrl_init function initializes a
+* Multicast Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_ctrl_init(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mftr_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_mftr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mftr_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 Multicast Forwarding Table Receive Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other Multicast Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object,
+* osm_mftr_rcv_ctrl_construct, osm_mftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_RCV_CTRL_H_ */
diff --git a/osm/opensm/osm_sa_mft_record.c b/osm/opensm/osm_sa_mft_record.c
new file mode 100644
index 0000000..a415fb9
--- /dev/null
+++ b/osm/opensm/osm_sa_mft_record.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 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.
+ *
+ */
+
+/*
+ * Abstract:
+ * Implementation of osm_mftr_rcv_t.
+ * This object represents the MulticastForwardingTable Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_MFTR_RCV_POOL_MIN_SIZE 32
+#define OSM_MFTR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_mftr_item
+{
+ cl_pool_item_t pool_item;
+ ib_mft_record_t rec;
+} osm_mftr_item_t;
+
+typedef struct _osm_mftr_search_ctxt
+{
+ const ib_mft_record_t* p_rcvd_rec;
+ ib_net64_t comp_mask;
+ cl_qlist_t* p_list;
+ osm_mftr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_mftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_construct(
+ IN osm_mftr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_destroy(
+ IN osm_mftr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_init(
+ IN osm_mftr_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_mftr_rcv_init );
+
+ osm_mftr_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_MFTR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_MFTR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_mftr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mftr_rcv_new_mftr(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid,
+ IN uint16_t const block,
+ IN uint8_t const position )
+{
+ osm_mftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ uint16_t position_block_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mftr_rcv_new_mftr );
+
+ p_rec_item = (osm_mftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mftr_rcv_new_mftr: ERR 4A02: "
+ "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_mftr_rcv_new_mftr: "
+ "New MulticastForwardingTable: sw 0x%016" PRIx64
+ "\n\t\t\t\tblock %u position %u lid 0x%02X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ),
+ block, position, cl_ntoh16( lid )
+ );
+ }
+
+ position_block_num = ((uint16_t)position << 12) |
+ (block & IB_MCAST_BLOCK_ID_MASK_HO);
+
+ memset( &p_rec_item->rec, 0, sizeof(ib_mft_record_t) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.position_block_num = cl_hton16( position_block_num );
+
+ /* copy the mft block */
+ osm_switch_get_mft_block( p_sw, block, position, p_rec_item->rec.mft );
+
+ 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_mftr_get_port_by_guid(
+ IN osm_mftr_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_mftr_get_port_by_guid ERR 4A04: "
+ "Invalid port GUID 0x%016" PRIx64 "\n",
+ port_guid );
+ p_port = NULL;
+ }
+
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mftr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_mftr_search_ctxt_t* const p_ctxt =
+ (osm_mftr_search_ctxt_t *)context;
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ const ib_mft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ osm_mftr_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 position_block_num_ho;
+ uint16_t min_block, max_block, block;
+ const osm_physp_t* p_physp;
+ uint8_t min_position, max_position, position;
+
+ /* In switches, the port guid is the node guid. */
+ p_port =
+ __osm_mftr_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_mftr_rcv_by_comp_mask: ERR 4A05: "
+ "Failed to find Port by Node Guid:0x%016" PRIx64
+ "\n",
+ cl_ntoh64( p_sw->p_node->node_info.node_guid )
+ );
+ return;
+ }
+
+ /* check that the requester 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_mftr_rcv_by_comp_mask: ERR 4A06: "
+ "Failed 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;
+
+ /* get the port 0 of the switch */
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+ /* compare the lids - if required */
+ if( comp_mask & IB_MFTR_COMPMASK_LID )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mftr_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;
+ }
+
+ position_block_num_ho = cl_ntoh16(p_rcvd_rec->position_block_num);
+
+ /* now we need to decide which blocks to output */
+ if( comp_mask & IB_MFTR_COMPMASK_BLOCK )
+ {
+ max_block = min_block = position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO;
+ if (max_block > osm_switch_get_mft_max_block_in_use( p_sw ) )
+ return;
+ }
+ else
+ {
+ /* use as many blocks as needed */
+ min_block = 0;
+ max_block = osm_switch_get_mft_max_block_in_use( p_sw );
+ }
+
+ /* need to decide which positions to output */
+ if ( comp_mask & IB_MFTR_COMPMASK_POSITION )
+ {
+ min_position = max_position = (position_block_num_ho & 0xF000) >> 12;
+ if (max_position > osm_switch_get_mft_max_position( p_sw ) )
+ return;
+ }
+ else
+ {
+ /* use as many positions as needed */
+ min_position = 0;
+ max_position = osm_switch_get_mft_max_position( p_sw );
+ }
+
+ /* so we can add these one by one ... */
+ for (block = min_block; block <= max_block; block++)
+ for (position = min_position; position <= max_position; position++)
+ __osm_mftr_rcv_new_mftr( p_rcv, p_sw, p_ctxt->p_list,
+ osm_port_get_base_lid(p_port),
+ block, position );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_process(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_mft_record_t* p_rcvd_rec;
+ ib_mft_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_mftr_search_ctxt_t context;
+ osm_mftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MFT_RECORD );
+
+ /* we only support SubnAdmGet and SubnAdmGetTable methods */
+ 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_mftr_rcv_process: ERR 4A08: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester 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_mftr_rcv_process: ERR 4A07: "
+ "Cannot find requester physical port\n" );
+ 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_mftr_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 SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A09: "
+ "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_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_mftr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_mftr_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_mft_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_mftr_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_mftr_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_mft_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_mftr_rcv_process: ERR 4A10: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_mftr_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.
+ */
+
+ memcpy( p_resp_sa_mad, p_rcvd_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 185 p 884) */
+ 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_mft_record_t) );
+
+ p_resp_rec = (ib_mft_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_mftr_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_mftr_rcv_process: ERR 4A11: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
diff --git a/osm/opensm/osm_sa_mft_record_ctrl.c b/osm/opensm/osm_sa_mft_record_ctrl.c
new file mode 100644
index 0000000..cf433a9
--- /dev/null
+++ b/osm/opensm/osm_sa_mft_record_ctrl.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 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.
+ *
+ */
+
+/*
+ * Abstract:
+ * Implementation of osm_mftr_rcv_ctrl_t.
+ * This object represents the MulticastForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_mft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mftr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mftr_rcv_process( ((osm_mftr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_construct(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_destroy(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_ctrl_init(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mftr_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_mftr_rcv_ctrl_init );
+
+ osm_mftr_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_RECORD,
+ __osm_mftr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_ctrl_init: ERR 4A01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
More information about the general
mailing list