[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