[ofa-general] [PATCH 1/2 v4] opensm: Storage organization for multicast groups

Slava Strebkov slavas at Voltaire.COM
Tue Sep 29 06:53:18 PDT 2009


Main purpose is to prepare infrastructure for (many) mgids to one mlid
compression. Proposed the following changes:
1.Element in mlid array is now a multicast group box.
2.mgrp_box keeps a list of mgroups sharing same mlid.
With introduction of compression, there will be many
multicast groups per mlid. Current implementation keeps
one mgid to one mlid ratio.
3.mgrp_box has a map of ports sharing same mlid. Ports sorted
by port guid. Port map is necessary for building spanning
tree per mgroup_box, not just for single mgroup.
4.Element in port map keeps a list of mgroups opened by this port.
This allows quick deletion of mgroups when port changes
state to DOWN.
5.Multicast processing functions use mgroup_box object instead
of mgroup.

Signed-off-by: Slava Strebkov <slavas at voltaire.com>
---
 opensm/include/opensm/osm_multicast.h  |  130 ++++++++++++++++++++++++++++++--
 opensm/include/opensm/osm_subnet.h     |   49 ++++++++++---
 opensm/opensm/osm_drop_mgr.c           |    2 +-
 opensm/opensm/osm_mcast_mgr.c          |  110 +++++++++++++--------------
 opensm/opensm/osm_multicast.c          |  108 ++++++++++++++++++++++++--
 opensm/opensm/osm_qos_policy.c         |   39 ++++++----
 opensm/opensm/osm_sa.c                 |   32 +++-----
 opensm/opensm/osm_sa_mcmember_record.c |   53 ++++++++++---
 opensm/opensm/osm_sa_path_record.c     |   32 ++++++--
 opensm/opensm/osm_subnet.c             |   33 +++++++--
 10 files changed, 440 insertions(+), 148 deletions(-)

diff --git a/opensm/include/opensm/osm_multicast.h b/opensm/include/opensm/osm_multicast.h
index 32bcb78..d4daf4b 100644
--- a/opensm/include/opensm/osm_multicast.h
+++ b/opensm/include/opensm/osm_multicast.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  *
@@ -97,8 +97,8 @@ BEGIN_C_DECLS
 */
 typedef struct osm_mgrp {
 	cl_fmap_item_t map_item;
+	cl_list_item_t box_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;
@@ -109,15 +109,13 @@ typedef struct osm_mgrp {
 *	map_item
 *		Map Item for fmap linkage.  Must be first element!!
 *
+*	box_item
+*		List Item for the group in mgroup box
+*
 *	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.
@@ -133,6 +131,71 @@ typedef struct osm_mgrp {
 * SEE ALSO
 *********/
 
+/****s* OpenSM: Multicast Group Holder/osm_mgrp_box_t
+* NAME
+*	osm_mgrp_box_t
+*
+* DESCRIPTION
+*	Holder for mgroups.
+*
+*	The osm_mgrp_box_t object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_mgrp_box {
+	cl_qmap_t mgrp_port_map;
+	cl_qlist_t mgrp_list;
+	ib_net16_t mlid;
+	osm_mtree_node_t *p_root;
+} osm_mgrp_box_t;
+/*
+* FIELDS
+*	mgrp_port_map
+*		Map sorted by GUID of osm_mgrp_port_t objects represents
+*		ports to be routed with same mlid
+*
+*	mgrp_list
+*		List of mgroups having same mlid
+*
+*	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.
+*
+* SEE ALSO
+*********/
+/****s* OpenSM: Multicast group Port /osm_mgrp_port_t
+* NAME
+*	osm_mgrp_port_t
+*
+* DESCRIPTION
+*	Holder for pointers to mgroups and port guid.
+*
+*
+* SYNOPSIS
+*/
+typedef struct osm_mgrp_port {
+	cl_map_item_t guid_item;
+	unsigned num_groups;
+	osm_port_t *p_port;
+} osm_mgrp_port_t;
+/*
+* FIELDS
+*	guid_item
+*		Map for ports. Must be first element
+*
+*	num_mgroups
+*		Number of mgroups opened by this port
+*
+*	p_mcm_port
+*		pointer to osm_mcm_port_t object
+*
+*/
 /****f* OpenSM: Multicast Group/osm_mgrp_new
 * NAME
 *	osm_mgrp_new
@@ -382,5 +445,58 @@ void osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 			  osm_mcm_port_t * mcm_port, ib_member_rec_t * mcmr);
 void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mpgr);
 
+/****f* OpenSM: Multicast Group Box /osm_mgrp_box_new
+* NAME
+*	osm_mgrp_box_new
+*
+* DESCRIPTION
+*	Allocates and initializes a Multicast Group Box for use.
+*
+* SYNOPSIS
+*/
+osm_mgrp_box_t *osm_mgrp_box_new(IN osm_subn_t * p_subn,
+					IN ib_net16_t mlid);
+/*
+* PARAMETERS
+*	p_subn
+*		(in) pointer to osm_subnet
+*	mlid
+*		[in] Multicast LID for this multicast group box.
+*
+* RETURN VALUES
+*	pointer to initialized osm_mgrp_box_t
+*	or NULL, if unsuccessful
+*
+* SEE ALSO
+*	Multicast Group Box, osm_mgrp_box_delete
+*********/
+/****f* OpenSM: Multicast Group Box /osm_mgrp_box_delete
+* NAME
+*	osm_mgrp_box_delete
+*
+* DESCRIPTION
+*	Removes  entry from  array of boxes
+*	Removes port from mgroup port list
+*
+* SYNOPSIS
+*/
+void osm_mgrp_box_delete(IN osm_subn_t * p_subn,
+				IN ib_net16_t mlid);
+/*
+* PARAMETERS
+*	p_subn
+*		[in] Pointer to  osm_subnet
+*
+*	mlid
+*		[in] box's mlid
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
 END_C_DECLS
 #endif				/* _OSM_MULTICAST_H_ */
diff --git a/opensm/include/opensm/osm_subnet.h b/opensm/include/opensm/osm_subnet.h
index 6c20de8..fe4695f 100644
--- a/opensm/include/opensm/osm_subnet.h
+++ b/opensm/include/opensm/osm_subnet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -69,6 +69,7 @@ BEGIN_C_DECLS
 #define OSM_SUBNET_VECTOR_CAPACITY			256
 struct osm_opensm;
 struct osm_qos_policy;
+struct osm_mgrp_box;
 
 /****h* OpenSM/Subnet
 * NAME
@@ -513,7 +514,7 @@ typedef struct osm_subn {
 	boolean_t coming_out_of_standby;
 	unsigned need_update;
 	cl_fmap_t mgrp_mgid_tbl;
-	void *mgroups[IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1];
+	void *mboxes[IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1];
 } osm_subn_t;
 /*
 * FIELDS
@@ -634,8 +635,8 @@ typedef struct osm_subn {
 *		This flag should be on during first non-master heavy
 *		(including pre-master discovery stage)
 *
-*	mgroups
-*		Array of pointers to all Multicast Group objects in the subnet.
+*	mboxes
+*		Array of pointers to all Multicast Group Box objects in the subnet.
 *		Indexed by MLID offset from base MLID.
 *
 * SEE ALSO
@@ -935,21 +936,21 @@ struct osm_port *osm_get_port_by_guid(IN osm_subn_t const *p_subn,
 *	osm_port_t
 *********/
 
-/****f* OpenSM: Subnet/osm_get_mgrp_by_mlid
+/****f* OpenSM: Subnet/osm_get_mgrp_box_by_mlid
 * NAME
-*	osm_get_mgrp_by_mlid
+*	osm_get_mgrp_box_by_mlid
 *
 * DESCRIPTION
-*	The looks for the given multicast group in the subnet table by mlid.
+*	The looks for the given multicast group box in the subnet table by mlid.
 *	NOTE: this code is not thread safe. Need to grab the lock before
 *	calling it.
 *
 * SYNOPSIS
 */
 static inline
-struct osm_mgrp *osm_get_mgrp_by_mlid(osm_subn_t const *p_subn, ib_net16_t mlid)
+struct osm_mgrp_box *osm_get_mgrp_box_by_mlid(osm_subn_t const *p_subn, ib_net16_t mlid)
 {
-	return p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO];
+	return p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO];
 }
 /*
 * PARAMETERS
@@ -960,7 +961,7 @@ struct osm_mgrp *osm_get_mgrp_by_mlid(osm_subn_t const *p_subn, ib_net16_t mlid)
 *		[in] The multicast group mlid in network order
 *
 * RETURN VALUES
-*	The multicast group structure pointer if found. NULL otherwise.
+*	The multicast group box structure pointer if found. NULL otherwise.
 *********/
 
 /****f* OpenSM: Helper/osm_get_physp_by_mad_addr
@@ -1116,5 +1117,33 @@ int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t * const p_opt);
 *********/
 int osm_subn_verify_config(osm_subn_opt_t * const p_opt);
 
+ib_net16_t osm_mgrp_box_get_mlid(IN struct osm_mgrp_box *p_mgrp_box);
+
+/****f* OpenSM: Subnet/osm_mgrp_box_get_mlid_by_mgid
+* NAME
+*       osm_mgrp_box_get_mlid_by_mgid
+*
+* DESCRIPTION
+*       The looks for multicast group by mgid. Returns mlid of found group
+*	or 0 if no group found.
+*	NOTE: this code is not thread safe. Need to grab the lock before
+*	calling it.
+*
+* SYNOPSIS
+*/
+ib_net16_t osm_mgrp_box_get_mlid_by_mgid(IN osm_subn_t const *p_subn,
+					IN const ib_gid_t * const p_mgid);
+/*
+* PARAMETERS
+*	p_subn
+*		[in] Pointer to an osm_subn_t object
+*
+*	p_mgid
+*		[in] Pointer to  multicast group mgid
+*
+* RETURN VALUES
+*	The multicast group mlid if found. 0 otherwise.
+*********/
+
 END_C_DECLS
 #endif				/* _OSM_SUBNET_H_ */
diff --git a/opensm/opensm/osm_drop_mgr.c b/opensm/opensm/osm_drop_mgr.c
index 4f98cc9..c86ee72 100644
--- a/opensm/opensm/osm_drop_mgr.c
+++ b/opensm/opensm/osm_drop_mgr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
diff --git a/opensm/opensm/osm_mcast_mgr.c b/opensm/opensm/osm_mcast_mgr.c
index 3894677..4fbae91 100644
--- a/opensm/opensm/osm_mcast_mgr.c
+++ b/opensm/opensm/osm_mcast_mgr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -111,14 +111,14 @@ static void mcast_mgr_purge_tree_node(IN osm_mtree_node_t * p_mtn)
 
 /**********************************************************************
  **********************************************************************/
-static void mcast_mgr_purge_tree(osm_sm_t * sm, IN osm_mgrp_t * p_mgrp)
+static void mcast_mgr_purge_tree(osm_sm_t * sm, IN osm_mgrp_box_t * p_mgrp_box)
 {
 	OSM_LOG_ENTER(sm->p_log);
 
-	if (p_mgrp->p_root)
-		mcast_mgr_purge_tree_node(p_mgrp->p_root);
+	if (p_mgrp_box->p_root)
+		mcast_mgr_purge_tree_node(p_mgrp_box->p_root);
 
-	p_mgrp->p_root = NULL;
+	p_mgrp_box->p_root = NULL;
 
 	OSM_LOG_EXIT(sm->p_log);
 }
@@ -126,28 +126,26 @@ static void mcast_mgr_purge_tree(osm_sm_t * sm, IN osm_mgrp_t * p_mgrp)
 /**********************************************************************
  **********************************************************************/
 static float osm_mcast_mgr_compute_avg_hops(osm_sm_t * sm,
-					    const osm_mgrp_t * p_mgrp,
+					    const osm_mgrp_box_t * p_mgrp_box,
 					    const osm_switch_t * p_sw)
 {
 	float avg_hops = 0;
 	uint32_t hops = 0;
 	uint32_t num_ports = 0;
-	const osm_mcm_port_t *p_mcm_port;
-	const cl_qmap_t *p_mcm_tbl;
+	const osm_mgrp_port_t *p_box_port;
 
 	OSM_LOG_ENTER(sm->p_log);
 
-	p_mcm_tbl = &p_mgrp->mcm_port_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)) {
-		hops += osm_switch_get_port_least_hops(p_sw, p_mcm_port->port);
+	for (p_box_port = (osm_mgrp_port_t *) cl_qmap_head(&p_mgrp_box->mgrp_port_map);
+	     p_box_port != (osm_mgrp_port_t *) cl_qmap_end(&p_mgrp_box->mgrp_port_map);
+	     p_box_port =
+	     (osm_mgrp_port_t *) cl_qmap_next(&p_box_port->guid_item)) {
+		hops += osm_switch_get_port_least_hops(p_sw, p_box_port->p_port);
 		num_ports++;
 	}
 
@@ -168,27 +166,27 @@ static float osm_mcast_mgr_compute_avg_hops(osm_sm_t * sm,
  of the group HCAs
  **********************************************************************/
 static float osm_mcast_mgr_compute_max_hops(osm_sm_t * sm,
-					    const osm_mgrp_t * p_mgrp,
+					    const osm_mgrp_box_t * p_mgrp_box,
 					    const osm_switch_t * p_sw)
 {
 	uint32_t max_hops = 0;
 	uint32_t hops = 0;
-	const osm_mcm_port_t *p_mcm_port;
-	const cl_qmap_t *p_mcm_tbl;
+	const osm_mgrp_port_t *p_box_port;
+	const cl_qmap_t *p_box_port_tbl;
 
 	OSM_LOG_ENTER(sm->p_log);
 
-	p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+	p_box_port_tbl = &p_mgrp_box->mgrp_port_map;
 
 	/*
 	   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)) {
-		hops = osm_switch_get_port_least_hops(p_sw, p_mcm_port->port);
+	for (p_box_port = (osm_mgrp_port_t *) cl_qmap_head(p_box_port_tbl);
+	     p_box_port != (osm_mgrp_port_t *) cl_qmap_end(p_box_port_tbl);
+	     p_box_port =
+	     (osm_mgrp_port_t *) cl_qmap_next(&p_box_port->guid_item)) {
+		hops = osm_switch_get_port_least_hops(p_sw, p_box_port->p_port);
 		if (hops > max_hops)
 			max_hops = hops;
 	}
@@ -210,7 +208,7 @@ static float osm_mcast_mgr_compute_max_hops(osm_sm_t * sm,
    of the multicast group.
 **********************************************************************/
 static osm_switch_t *mcast_mgr_find_optimal_switch(osm_sm_t * sm,
-						   const osm_mgrp_t * p_mgrp)
+						   const osm_mgrp_box_t * p_mgrp_box)
 {
 	cl_qmap_t *p_sw_tbl;
 	const osm_switch_t *p_sw;
@@ -227,7 +225,7 @@ static osm_switch_t *mcast_mgr_find_optimal_switch(osm_sm_t * sm,
 
 	p_sw_tbl = &sm->p_subn->sw_guid_tbl;
 
-	CL_ASSERT(!osm_mgrp_is_empty(p_mgrp));
+	CL_ASSERT(!osm_mgrp_is_empty(p_mgrp_box));
 
 	for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
 	     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl);
@@ -236,9 +234,9 @@ static osm_switch_t *mcast_mgr_find_optimal_switch(osm_sm_t * sm,
 			continue;
 
 		if (use_avg_hops)
-			hops = osm_mcast_mgr_compute_avg_hops(sm, p_mgrp, p_sw);
+			hops = osm_mcast_mgr_compute_avg_hops(sm, p_mgrp_box, p_sw);
 		else
-			hops = osm_mcast_mgr_compute_max_hops(sm, p_mgrp, p_sw);
+			hops = osm_mcast_mgr_compute_max_hops(sm, p_mgrp_box, p_sw);
 
 		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
 			"Switch 0x%016" PRIx64 ", hops = %f\n",
@@ -267,7 +265,7 @@ static osm_switch_t *mcast_mgr_find_optimal_switch(osm_sm_t * sm,
    This function returns the existing or optimal root swtich for the tree.
 **********************************************************************/
 static osm_switch_t *mcast_mgr_find_root_switch(osm_sm_t * sm,
-						const osm_mgrp_t * p_mgrp)
+						const osm_mgrp_box_t * p_mgrp_box)
 {
 	const osm_switch_t *p_sw = NULL;
 
@@ -279,7 +277,7 @@ static osm_switch_t *mcast_mgr_find_root_switch(osm_sm_t * sm,
 	   the root will be always on the first switch attached to it.
 	   - Very bad ...
 	 */
-	p_sw = mcast_mgr_find_optimal_switch(sm, p_mgrp);
+	p_sw = mcast_mgr_find_optimal_switch(sm, p_mgrp_box);
 
 	OSM_LOG_EXIT(sm->p_log);
 	return (osm_switch_t *) p_sw;
@@ -354,7 +352,7 @@ static int mcast_mgr_set_mft_block(osm_sm_t * sm, IN osm_switch_t * p_sw,
   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 mcast_mgr_subdivide(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
+static void mcast_mgr_subdivide(osm_sm_t * sm, osm_mgrp_box_t * p_mgrp_box,
 				osm_switch_t * p_sw, cl_qlist_t * p_list,
 				cl_qlist_t * list_array, uint8_t array_size)
 {
@@ -365,7 +363,7 @@ static void mcast_mgr_subdivide(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
 
 	OSM_LOG_ENTER(sm->p_log);
 
-	mlid_ho = cl_ntoh16(osm_mgrp_get_mlid(p_mgrp));
+	mlid_ho = cl_ntoh16(osm_mgrp_box_get_mlid(p_mgrp_box));
 
 	/*
 	   For Multicast Groups, we want not to count on previous
@@ -455,7 +453,7 @@ static void mcast_mgr_purge_list(osm_sm_t * sm, cl_qlist_t * p_list)
 
   The function returns the newly created mtree node element.
 **********************************************************************/
-static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
+static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, osm_mgrp_box_t * p_mgrp_box,
 					  osm_switch_t * p_sw,
 					  cl_qlist_t * p_list, uint8_t depth,
 					  uint8_t upstream_port,
@@ -481,7 +479,7 @@ static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
 
 	node_guid = osm_node_get_node_guid(p_sw->p_node);
 	node_guid_ho = cl_ntoh64(node_guid);
-	mlid_ho = cl_ntoh16(osm_mgrp_get_mlid(p_mgrp));
+	mlid_ho = cl_ntoh16(osm_mgrp_box_get_mlid(p_mgrp_box));
 
 	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
 		"Routing MLID 0x%X through switch 0x%" PRIx64
@@ -558,7 +556,7 @@ static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
 	for (i = 0; i < max_children; i++)
 		cl_qlist_init(&list_array[i]);
 
-	mcast_mgr_subdivide(sm, p_mgrp, p_sw, p_list, list_array, max_children);
+	mcast_mgr_subdivide(sm, p_mgrp_box, p_sw, p_list, list_array, max_children);
 
 	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
 
@@ -641,7 +639,7 @@ static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, osm_mgrp_t * p_mgrp,
 			CL_ASSERT(p_remote_physp);
 
 			p_mtn->child_array[i] =
-			    mcast_mgr_branch(sm, p_mgrp, p_remote_node->sw,
+			    mcast_mgr_branch(sm, p_mgrp_box, p_remote_node->sw,
 					     p_port_list, depth,
 					     osm_physp_get_port_num
 					     (p_remote_physp), p_max_depth);
@@ -677,11 +675,10 @@ Exit:
 /**********************************************************************
  **********************************************************************/
 static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm,
-						     osm_mgrp_t * p_mgrp)
+						     osm_mgrp_box_t * p_mgrp_box)
 {
-	const cl_qmap_t *p_mcm_tbl;
-	const osm_mcm_port_t *p_mcm_port;
 	uint32_t num_ports;
+	const osm_mgrp_port_t *p_mgrp_port;
 	cl_qlist_t port_list;
 	osm_switch_t *p_sw;
 	osm_mcast_work_obj_t *p_wobj;
@@ -699,14 +696,13 @@ static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm,
 	   on multicast forwarding table information if the user wants to
 	   preserve existing multicast routes.
 	 */
-	mcast_mgr_purge_tree(sm, p_mgrp);
+	mcast_mgr_purge_tree(sm, p_mgrp_box);
 
-	p_mcm_tbl = &p_mgrp->mcm_port_tbl;
-	num_ports = cl_qmap_count(p_mcm_tbl);
+	num_ports = cl_qmap_count(&p_mgrp_box->mgrp_port_map);
 	if (num_ports == 0) {
 		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
 			"MLID 0x%X has no members - nothing to do\n",
-			cl_ntoh16(osm_mgrp_get_mlid(p_mgrp)));
+			cl_ntoh16(osm_mgrp_box_get_mlid(p_mgrp_box)));
 		goto Exit;
 	}
 
@@ -726,11 +722,11 @@ static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm,
 	   Locate the switch around which to create the spanning
 	   tree for this multicast group.
 	 */
-	p_sw = mcast_mgr_find_root_switch(sm, p_mgrp);
+	p_sw = mcast_mgr_find_root_switch(sm, p_mgrp_box);
 	if (p_sw == NULL) {
 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A08: "
 			"Unable to locate a suitable switch for group 0x%X\n",
-			cl_ntoh16(osm_mgrp_get_mlid(p_mgrp)));
+			cl_ntoh16(osm_mgrp_box_get_mlid(p_mgrp_box)));
 		status = IB_ERROR;
 		goto Exit;
 	}
@@ -738,20 +734,20 @@ static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm,
 	/*
 	   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)) {
+	for (p_mgrp_port = (osm_mgrp_port_t *) cl_qmap_head(&p_mgrp_box->mgrp_port_map);
+	     p_mgrp_port != (osm_mgrp_port_t *) cl_qmap_end(&p_mgrp_box->mgrp_port_map);
+	     p_mgrp_port =
+	     (osm_mgrp_port_t *) cl_qmap_next(&p_mgrp_port->guid_item)) {
 		/*
 		   Acquire the port object for this port guid, then create
 		   the new worker object to build the list.
 		 */
-		p_wobj = mcast_work_obj_new(p_mcm_port->port);
+		p_wobj = mcast_work_obj_new(p_mgrp_port->p_port);
 		if (p_wobj == NULL) {
 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A10: "
 				"Insufficient memory to route port 0x%016"
 				PRIx64 "\n",
-				cl_ntoh64(osm_port_get_guid(p_mcm_port->port)));
+				cl_ntoh64(p_mgrp_port->p_port->guid));
 			continue;
 		}
 
@@ -759,12 +755,12 @@ static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm,
 	}
 
 	count = cl_qlist_count(&port_list);
-	p_mgrp->p_root = mcast_mgr_branch(sm, p_mgrp, p_sw, &port_list, 0, 0,
+	p_mgrp_box->p_root = mcast_mgr_branch(sm, p_mgrp_box, p_sw, &port_list, 0, 0,
 					  &max_depth);
 
 	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
 		"Configured MLID 0x%X for %u ports, max tree depth = %u\n",
-		cl_ntoh16(osm_mgrp_get_mlid(p_mgrp)), count, max_depth);
+		cl_ntoh16(osm_mgrp_box_get_mlid(p_mgrp_box)), count, max_depth);
 
 Exit:
 	OSM_LOG_EXIT(sm->p_log);
@@ -971,7 +967,7 @@ Exit:
 static ib_api_status_t mcast_mgr_process_mlid(osm_sm_t * sm, uint16_t mlid)
 {
 	ib_api_status_t status = IB_SUCCESS;
-	osm_mgrp_t *mgrp;
+	osm_mgrp_box_t *p_mgrp_box;
 
 	OSM_LOG_ENTER(sm->p_log);
 
@@ -983,9 +979,9 @@ static ib_api_status_t mcast_mgr_process_mlid(osm_sm_t * sm, uint16_t mlid)
 	   port in the group. */
 	mcast_mgr_clear(sm, mlid);
 
-	mgrp = osm_get_mgrp_by_mlid(sm->p_subn, cl_hton16(mlid));
-	if (mgrp) {
-		status = mcast_mgr_build_spanning_tree(sm, mgrp);
+	p_mgrp_box = osm_get_mgrp_box_by_mlid(sm->p_subn, cl_hton16(mlid));
+	if (p_mgrp_box) {
+		status = mcast_mgr_build_spanning_tree(sm, p_mgrp_box);
 		if (status != IB_SUCCESS)
 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A17: "
 				"Unable to create spanning tree (%s) for mlid "
@@ -1065,7 +1061,7 @@ int osm_mcast_mgr_process(osm_sm_t * sm)
 
 	for (i = 0; i <= sm->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
 	     i++)
-		if (sm->p_subn->mgroups[i] || sm->mlids_req[i])
+		if (sm->p_subn->mboxes[i] || sm->mlids_req[i])
 			mcast_mgr_process_mlid(sm, i + IB_LID_MCAST_START_HO);
 
 	memset(sm->mlids_req, 0, sm->mlids_req_max);
diff --git a/opensm/opensm/osm_multicast.c b/opensm/opensm/osm_multicast.c
index 5a10003..01c90d8 100644
--- a/opensm/opensm/osm_multicast.c
+++ b/opensm/opensm/osm_multicast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  *
@@ -51,6 +51,18 @@
 #include <opensm/osm_inform.h>
 #include <opensm/osm_opensm.h>
 
+static osm_mgrp_port_t *osm_mgrp_port_new(osm_port_t *p_port)
+{
+	osm_mgrp_port_t *p_mgrp_port =
+		(osm_mgrp_port_t *) malloc(sizeof(osm_mgrp_port_t));
+	if (!p_mgrp_port) {
+		return NULL;
+	}
+	memset(p_mgrp_port, 0, sizeof(*p_mgrp_port));
+	p_mgrp_port->p_port = p_port;
+	return p_mgrp_port;
+}
+
 /**********************************************************************
  **********************************************************************/
 void osm_mgrp_delete(IN osm_mgrp_t * p_mgrp)
@@ -69,8 +81,6 @@ void osm_mgrp_delete(IN osm_mgrp_t * p_mgrp)
 		    (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);
 
 	free(p_mgrp);
 }
@@ -99,8 +109,6 @@ void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mgrp)
 	if (mgrp->full_members)
 		return;
 
-	osm_mtree_destroy(mgrp->p_root);
-	mgrp->p_root = NULL;
 
 	while (cl_qmap_count(&mgrp->mcm_port_tbl)) {
 		mcm_port = (osm_mcm_port_t *)cl_qmap_head(&mgrp->mcm_port_tbl);
@@ -114,7 +122,6 @@ void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mgrp)
 		return;
 
 	cl_fmap_remove_item(&subn->mgrp_mgid_tbl, &mgrp->map_item);
-	subn->mgroups[cl_ntoh16(mgrp->mlid) - IB_LID_MCAST_START_HO] = NULL;
 	free(mgrp);
 }
 
@@ -157,6 +164,7 @@ osm_mcm_port_t *osm_mgrp_add_port(IN osm_subn_t * subn, osm_log_t * log,
 	cl_map_item_t *prev_item;
 	uint8_t prev_join_state = 0, join_state = mcmr->scope_state;
 	uint8_t prev_scope;
+	osm_mgrp_box_t *p_mgrp_box;
 
 	if (osm_log_is_active(log, OSM_LOG_VERBOSE)) {
 		char gid_str[INET6_ADDRSTRLEN];
@@ -193,7 +201,20 @@ osm_mcm_port_t *osm_mgrp_add_port(IN osm_subn_t * subn, osm_log_t * log,
 					      prev_join_state | join_state);
 	} else {
 		cl_qlist_insert_tail(&port->mcm_list, &mcm_port->list_item);
-		osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid);
+		p_mgrp_box = osm_get_mgrp_box_by_mlid(subn, mgrp->mlid);
+		osm_mgrp_port_t *p_mgrp_port = (osm_mgrp_port_t *)
+			cl_qmap_get(&p_mgrp_box->mgrp_port_map, ib_gid_get_guid(&mcm_port->port_gid));
+		if (p_mgrp_port ==
+			(osm_mgrp_port_t *) cl_qmap_end(&p_mgrp_box->mgrp_port_map)) {
+			/* new port to mlid */
+			p_mgrp_port = osm_mgrp_port_new(mcm_port->port);
+			if (!p_mgrp_port) {
+				return NULL;
+			}
+			cl_qmap_insert(&p_mgrp_box->mgrp_port_map,
+				ib_gid_get_guid(&mcm_port->port_gid), &p_mgrp_port->guid_item);
+		}
+		osm_sm_reroute_mlid(&subn->p_osm->sm, p_mgrp_box->mlid);
 	}
 
 	/* o15.0.1.11: copy the join state */
@@ -214,6 +235,7 @@ void osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 {
 	uint8_t join_state = mcmr->scope_state & 0xf;
 	uint8_t port_join_state, new_join_state;
+	osm_mgrp_box_t *p_mgrp_box;
 
 	/*
 	 * according to the same o15-0.1.14 we get the stored
@@ -222,6 +244,7 @@ void osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 	 */
 	port_join_state = mcm_port->scope_state & 0x0F;
 	new_join_state = port_join_state & ~join_state;
+	p_mgrp_box = osm_get_mgrp_box_by_mlid(subn, mgrp->mlid);
 
 	if (osm_log_is_active(log, OSM_LOG_VERBOSE)) {
 		char gid_str[INET6_ADDRSTRLEN];
@@ -242,14 +265,27 @@ void osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 			port_join_state, new_join_state);
 		mcmr->scope_state = mcm_port->scope_state;
 	} else {
+		osm_mgrp_port_t *p_mgrp_port;
 		mcmr->scope_state = mcm_port->scope_state;
 		OSM_LOG(log, OSM_LOG_DEBUG, "removing port 0x%" PRIx64 "\n",
 			cl_ntoh64(mcm_port->port->guid));
 		cl_qmap_remove_item(&mgrp->mcm_port_tbl, &mcm_port->map_item);
 		cl_qlist_remove_item(&mcm_port->port->mcm_list,
 				     &mcm_port->list_item);
+		p_mgrp_port = (osm_mgrp_port_t *)
+			cl_qmap_get(&p_mgrp_box->mgrp_port_map, mcm_port->port->guid);
+		if (p_mgrp_port !=
+			(osm_mgrp_port_t *) cl_qmap_end(&p_mgrp_box->mgrp_port_map)) {
+			p_mgrp_port->num_groups--;
+			if (0 == p_mgrp_port->num_groups) {
+				/* No mgroups registered on this port for current mlid */
+				cl_qmap_remove_item(&p_mgrp_box->mgrp_port_map,
+					&p_mgrp_port->guid_item);
+				free(p_mgrp_port);
+			}
+		}
 		osm_mcm_port_delete(mcm_port);
-		osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid);
+		osm_sm_reroute_mlid(&subn->p_osm->sm, p_mgrp_box->mlid);
 	}
 
 	/* no more full members so the group will be deleted after re-route
@@ -258,6 +294,12 @@ void osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 	    !(new_join_state & IB_JOIN_STATE_FULL) &&
 	    --mgrp->full_members == 0) {
 		mgrp_send_notice(subn, log, mgrp, 67);
+		cl_qlist_remove_item(&p_mgrp_box->mgrp_list, &mgrp->box_item);
+		if (0 == cl_qlist_count(&p_mgrp_box->mgrp_list)) {
+			/* empty mgrp_box */
+			osm_mgrp_box_delete(subn,p_mgrp_box->mlid);
+		}
+
 		osm_mgrp_cleanup(subn, mgrp);
 	}
 }
@@ -266,8 +308,16 @@ void osm_mgrp_delete_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
 			  ib_net64_t port_guid)
 {
 	ib_member_rec_t mcmrec;
-	cl_map_item_t *item = cl_qmap_get(&mgrp->mcm_port_tbl, port_guid);
+	osm_mgrp_box_t *p_mgrp_box;
+	osm_mgrp_port_t *p_mgrp_port;
 
+	cl_map_item_t *item = cl_qmap_get(&mgrp->mcm_port_tbl, port_guid);
+	p_mgrp_box = osm_get_mgrp_box_by_mlid(subn, mgrp->mlid);
+	p_mgrp_port = (osm_mgrp_port_t *)
+		cl_qmap_remove(&p_mgrp_box->mgrp_port_map, port_guid);
+	if (p_mgrp_port != (osm_mgrp_port_t *)cl_qmap_end(&p_mgrp_box->mgrp_port_map)) {
+		free(p_mgrp_port);
+	}
 	if (item != cl_qmap_end(&mgrp->mcm_port_tbl)) {
 		mcmrec.scope_state = 0xf;
 		osm_mgrp_remove_port(subn, log, mgrp, (osm_mcm_port_t *) item,
@@ -296,3 +346,43 @@ boolean_t osm_mgrp_is_port_present(IN const osm_mgrp_t * p_mgrp,
 		*pp_mcm_port = NULL;
 	return FALSE;
 }
+
+/**********************************************************************
+ **********************************************************************/
+osm_mgrp_box_t *osm_mgrp_box_new(IN osm_subn_t * p_subn,ib_net16_t mlid)
+{
+	osm_mgrp_box_t *p_mgrp_box;
+	p_mgrp_box =
+		p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] =
+		(osm_mgrp_box_t *) calloc(1,sizeof(*p_mgrp_box));
+	if (!p_mgrp_box)
+		return NULL;
+	p_mgrp_box->mlid = mlid;
+	cl_qmap_init(&p_mgrp_box->mgrp_port_map);
+	cl_qlist_init(&p_mgrp_box->mgrp_list);
+	return p_mgrp_box;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mgrp_box_delete(IN osm_subn_t *p_subn, ib_net16_t mlid)
+{
+	osm_mgrp_port_t *p_osm_mgr_port;
+	cl_map_item_t *p_item;
+	osm_mgrp_box_t *p_mgrp_box =
+	p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO];
+	p_item = cl_qmap_head(&p_mgrp_box->mgrp_port_map);
+	/* Delete ports shared same MLID */
+	while (p_item != cl_qmap_end(&p_mgrp_box->mgrp_port_map)) {
+		p_osm_mgr_port = (osm_mgrp_port_t *) p_item;
+		cl_qmap_remove_item(&p_mgrp_box->mgrp_port_map, p_item);
+		p_item = cl_qmap_head(&p_mgrp_box->mgrp_port_map);
+		free(p_osm_mgr_port);
+	}
+	/* Remove mgrp from this MLID */
+	cl_qlist_remove_all(&p_mgrp_box->mgrp_list);
+	/* Destroy the mtree_node structure */
+	osm_mtree_destroy(p_mgrp_box->p_root);
+	p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = NULL;
+	free(p_mgrp_box);
+}
diff --git a/opensm/opensm/osm_qos_policy.c b/opensm/opensm/osm_qos_policy.c
index 9b72293..6c0a1e6 100644
--- a/opensm/opensm/osm_qos_policy.c
+++ b/opensm/opensm/osm_qos_policy.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -773,6 +773,8 @@ static void __qos_policy_validate_pkey(
 	uint32_t flow;
 	uint8_t hop;
 	osm_mgrp_t * p_mgrp;
+	osm_mgrp_box_t * p_mgrp_box;
+	cl_list_item_t *p_item;
 
 	if (!p_qos_policy || !p_qos_match_rule || !p_prtn)
 		return;
@@ -796,28 +798,33 @@ static void __qos_policy_validate_pkey(
 	if (!p_prtn->mlid)
 		return;
 
-	p_mgrp = osm_get_mgrp_by_mlid(p_qos_policy->p_subn, p_prtn->mlid);
-	if (!p_mgrp) {
+	p_mgrp_box = osm_get_mgrp_box_by_mlid(p_qos_policy->p_subn, p_prtn->mlid);
+	if (!p_mgrp_box) {
 		OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR,
-			"ERR AC16: MCast group for partition with "
+			"ERR AC16: MCast group box for partition with "
 			"pkey 0x%04X not found\n",
 			cl_ntoh16(p_prtn->pkey));
 		return;
 	}
 
-	CL_ASSERT((cl_ntoh16(p_mgrp->mcmember_rec.pkey) & 0x7fff) ==
-		  (cl_ntoh16(p_prtn->pkey) & 0x7fff));
-
-	ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
-				  &sl, &flow, &hop);
-	if (sl != p_prtn->sl) {
-		OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_DEBUG,
-			"Updating MCGroup (MLID 0x%04x) SL to "
-			"match partition SL (%u)\n",
-			cl_hton16(p_mgrp->mcmember_rec.mlid),
-			p_prtn->sl);
-		p_mgrp->mcmember_rec.sl_flow_hop =
+	p_item = cl_qlist_head(&p_mgrp_box->mgrp_list);
+	while (p_item != cl_qlist_end(&p_mgrp_box->mgrp_list)) {
+		p_mgrp = (osm_mgrp_t *) PARENT_STRUCT(p_item, osm_mgrp_t,
+			box_item);
+		p_item = cl_qlist_next(p_item);
+		CL_ASSERT((cl_ntoh16(p_mgrp->mcmember_rec.pkey) & 0x7fff) ==
+			(cl_ntoh16(p_prtn->pkey) & 0x7fff));
+		ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+			&sl, &flow, &hop);
+		if (sl != p_prtn->sl) {
+			OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_DEBUG,
+				"Updating MCGroup (MLID 0x%04x) SL to "
+				"match partition SL (%u)\n",
+				cl_hton16(p_mgrp->mcmember_rec.mlid),
+				p_prtn->sl);
+			p_mgrp->mcmember_rec.sl_flow_hop =
 			ib_member_set_sl_flow_hop(p_prtn->sl, flow, hop);
+		}
 	}
 }
 
diff --git a/opensm/opensm/osm_sa.c b/opensm/opensm/osm_sa.c
index 02737c2..a5d8945 100644
--- a/opensm/opensm/osm_sa.c
+++ b/opensm/opensm/osm_sa.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -706,18 +706,17 @@ static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
 {
 	struct opensm_dump_context dump_context;
 	osm_mgrp_t *p_mgrp;
-	int i;
 
 	dump_context.p_osm = p_osm;
 	dump_context.file = file;
 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast\n");
 	cl_plock_acquire(&p_osm->lock);
-	for (i = 0; i <= p_osm->subn.max_mcast_lid_ho - IB_LID_MCAST_START_HO;
-	     i++) {
-		p_mgrp = p_osm->subn.mgroups[i];
-		if (p_mgrp)
-			sa_dump_one_mgrp(p_mgrp, &dump_context);
+	p_mgrp = (osm_mgrp_t*)cl_fmap_head(&p_osm->subn.mgrp_mgid_tbl);
+	while (p_mgrp != (osm_mgrp_t*)cl_fmap_end(&p_osm->subn.mgrp_mgid_tbl)) {
+		sa_dump_one_mgrp(p_mgrp, &dump_context);
+		p_mgrp = (osm_mgrp_t*) cl_fmap_next(&p_mgrp->map_item);
 	}
+
 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform\n");
 	cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
 			    sa_dump_one_inform, &dump_context);
@@ -740,22 +739,15 @@ static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid,
 				unsigned well_known)
 {
 	ib_net64_t comp_mask;
-	osm_mgrp_t *p_mgrp;
+	osm_mgrp_t *p_mgrp = NULL;
+	cl_fmap_item_t *p_fitem;
 
 	cl_plock_excl_acquire(&p_osm->lock);
 
-	p_mgrp = osm_get_mgrp_by_mlid(&p_osm->subn, mlid);
-	if (p_mgrp) {
-		if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
-			    sizeof(ib_gid_t))) {
-			OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
-				"mgrp %04x is already here.", cl_ntoh16(mlid));
-			goto _out;
-		}
-		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
-			"mlid %04x is already used by another MC group. Will "
-			"request clients reregistration.\n", cl_ntoh16(mlid));
-		p_mgrp = NULL;
+	p_fitem = cl_fmap_get(&p_osm->subn.mgrp_mgid_tbl, &p_mcm_rec->mgid);
+	if (p_fitem != cl_fmap_end(&p_osm->subn.mgrp_mgid_tbl)) {
+		OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+			"mgrp %04x is already here.", cl_ntoh16(mlid));
 		goto _out;
 	}
 
diff --git a/opensm/opensm/osm_sa_mcmember_record.c b/opensm/opensm/osm_sa_mcmember_record.c
index 8f7816b..b39f986 100644
--- a/opensm/opensm/osm_sa_mcmember_record.c
+++ b/opensm/opensm/osm_sa_mcmember_record.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -121,12 +121,12 @@ static ib_net16_t get_new_mlid(osm_sa_t * sa, ib_net16_t requested_mlid)
 
 	if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO
 	    && cl_ntoh16(requested_mlid) <= p_subn->max_mcast_lid_ho
-	    && !osm_get_mgrp_by_mlid(p_subn, requested_mlid))
+	    && !osm_get_mgrp_box_by_mlid(p_subn, requested_mlid))
 		return requested_mlid;
 
 	max = p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO + 1;
 	for (i = 0; i < max; i++)
-		if (!sa->p_subn->mgroups[i])
+		if (!sa->p_subn->mboxes[i])
 			return cl_hton16(i + IB_LID_MCAST_START_HO);
 
 	return 0;
@@ -730,10 +730,11 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 					     IN const osm_physp_t * p_physp,
 					     OUT osm_mgrp_t ** pp_mgrp)
 {
-	ib_net16_t mlid;
+	ib_net16_t mlid,existed_mlid;
 	unsigned zero_mgid, i;
 	uint8_t scope;
 	ib_gid_t *p_mgid;
+	osm_mgrp_box_t *p_mgrp_box;
 	ib_api_status_t status = IB_SUCCESS;
 	ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec;	/* copy for modifications */
 
@@ -811,6 +812,10 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 		goto Exit;
 	}
 
+	/* check if there is mgrp_box matched to requested mgid */
+	if (0 != (existed_mlid = osm_mgrp_box_get_mlid_by_mgid(sa->p_subn, p_mgid))) {
+		mlid = existed_mlid;
+	}
 	/* create a new MC Group */
 	*pp_mgrp = osm_mgrp_new(mlid);
 	if (*pp_mgrp == NULL) {
@@ -833,11 +838,28 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 	(*pp_mgrp)->mcmember_rec.pkt_life &= 0x3f;
 	(*pp_mgrp)->mcmember_rec.pkt_life |= 2 << 6;	/* exactly */
 
+	/* get mgrp_box for selected mlid */
+	p_mgrp_box = osm_get_mgrp_box_by_mlid(sa->p_subn, mlid);
+	if (!p_mgrp_box) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Creating new mgrp_box for mlid:0x%04x\n",
+			cl_ntoh16(mlid));
+		p_mgrp_box = osm_mgrp_box_new(sa->p_subn, mlid);
+		if (!p_mgrp_box) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B08: "
+				"osm_mgrp_box_new failed\n");
+			osm_mgrp_delete(*pp_mgrp);
+			free_mlid(sa, mlid);
+			status = IB_INSUFFICIENT_MEMORY;
+			goto Exit;
+		}
+	}
+
 	/* Insert the new group in the data base */
 	cl_fmap_insert(&sa->p_subn->mgrp_mgid_tbl,
 		       &(*pp_mgrp)->mcmember_rec.mgid, &(*pp_mgrp)->map_item);
-	sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = *pp_mgrp;
-
+	sa->p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = p_mgrp_box;
+	cl_qlist_insert_tail(&p_mgrp_box->mgrp_list, &(*pp_mgrp)->box_item);
 Exit:
 	OSM_LOG_EXIT(sa->p_log);
 	return status;
@@ -1173,6 +1195,13 @@ static void mcmr_rcv_join_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 		goto Exit;
 	}
 
+	if (is_new_group) {
+		osm_mgrp_port_t *p_mgrp_port;
+		osm_mgrp_box_t *p_mgrp_box = osm_get_mgrp_box_by_mlid(sa->p_subn, p_mgrp->mlid);
+		p_mgrp_port = (osm_mgrp_port_t *)
+			cl_qmap_get(&p_mgrp_box->mgrp_port_map, portguid);
+		p_mgrp_port->num_groups++;
+	}
 	/* Release the lock as we don't need it. */
 	CL_PLOCK_RELEASE(sa->p_lock);
 
@@ -1386,7 +1415,6 @@ static void mcmr_query_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 	osm_physp_t *p_req_physp;
 	boolean_t trusted_req;
 	osm_mgrp_t *p_mgrp;
-	int i;
 
 	OSM_LOG_ENTER(sa->p_log);
 
@@ -1415,12 +1443,11 @@ static void mcmr_query_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 	CL_PLOCK_ACQUIRE(sa->p_lock);
 
 	/* simply go over all MCGs and match */
-	for (i = 0; i <= sa->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
-	     i++) {
-		p_mgrp = sa->p_subn->mgroups[i];
-		if (p_mgrp)
-			mcmr_by_comp_mask(sa, p_rcvd_rec, comp_mask, p_mgrp,
-					  p_req_physp, trusted_req, &rec_list);
+	p_mgrp = (osm_mgrp_t *) cl_fmap_head(&sa->p_subn->mgrp_mgid_tbl);
+	while (p_mgrp != (osm_mgrp_t *) cl_fmap_end(&sa->p_subn->mgrp_mgid_tbl)) {
+		mcmr_by_comp_mask(sa, p_rcvd_rec, comp_mask, p_mgrp,
+					p_req_physp, trusted_req, &rec_list);
+		p_mgrp = (osm_mgrp_t *) cl_fmap_next(&p_mgrp->map_item);
 	}
 
 	CL_PLOCK_RELEASE(sa->p_lock);
diff --git a/opensm/opensm/osm_sa_path_record.c b/opensm/opensm/osm_sa_path_record.c
index 75d9516..6a63092 100644
--- a/opensm/opensm/osm_sa_path_record.c
+++ b/opensm/opensm/osm_sa_path_record.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved.
@@ -1433,12 +1433,13 @@ static void pr_rcv_process_pair(IN osm_sa_t * sa, IN const osm_madw_t * p_madw,
 
 /**********************************************************************
  **********************************************************************/
-static osm_mgrp_t *pr_get_mgrp(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
+static osm_mgrp_box_t *pr_get_mgrp_box(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
 {
 	ib_path_rec_t *p_pr;
 	const ib_sa_mad_t *p_sa_mad;
 	ib_net64_t comp_mask;
 	osm_mgrp_t *mgrp = NULL;
+	osm_mgrp_box_t *mgrp_box = NULL;
 
 	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);
@@ -1454,6 +1455,8 @@ static osm_mgrp_t *pr_get_mgrp(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
 				  sizeof gid_str));
 		goto Exit;
 	}
+	if (mgrp)
+		mgrp_box = osm_get_mgrp_box_by_mlid(sa->p_subn, mgrp->mlid);
 
 	if (comp_mask & IB_PR_COMPMASK_DLID) {
 		if (mgrp) {
@@ -1465,18 +1468,18 @@ static osm_mgrp_t *pr_get_mgrp(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
 					"MC group MLID 0x%x does not match "
 					"PathRecord destination LID 0x%x\n",
 					mgrp->mlid, p_pr->dlid);
-				mgrp = NULL;
+				mgrp_box = NULL;
 				goto Exit;
 			}
 		} else
-		    if (!(mgrp = osm_get_mgrp_by_mlid(sa->p_subn, p_pr->dlid)))
+		    if (!(mgrp_box = osm_get_mgrp_box_by_mlid(sa->p_subn, p_pr->dlid)))
 			OSM_LOG(sa->p_log, OSM_LOG_ERROR,
 				"ERR 1F11: " "No MC group found for PathRecord "
 				"destination LID 0x%x\n", p_pr->dlid);
 	}
 
 Exit:
-	return mgrp;
+	return mgrp_box;
 }
 
 /**********************************************************************
@@ -1691,20 +1694,31 @@ McastDest:
 	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Multicast destination requested\n");
 	{
 		osm_mgrp_t *p_mgrp = NULL;
-		ib_api_status_t status;
+		ib_api_status_t status = IB_SUCCESS;
 		osm_pr_item_t *p_pr_item;
 		uint32_t flow_label;
 		uint8_t sl;
 		uint8_t hop_limit;
+		cl_list_item_t *p_item;
+		osm_mgrp_box_t *p_mgrp_box = NULL;
 
 		/* First, get the MC info */
-		p_mgrp = pr_get_mgrp(sa, p_madw);
+		p_mgrp_box = pr_get_mgrp_box(sa, p_madw);
 
-		if (!p_mgrp)
+		if (!p_mgrp_box)
 			goto Unlock;
 
 		/* Make sure the rest of the PathRecord matches the MC group attributes */
-		status = pr_match_mgrp_attributes(sa, p_madw, p_mgrp);
+		for (p_item = cl_qlist_head(&p_mgrp_box->mgrp_list);
+			p_item != cl_qlist_end(&p_mgrp_box->mgrp_list);
+			p_item = cl_qlist_next(p_item)) {
+			p_mgrp = (osm_mgrp_t*)PARENT_STRUCT(p_item, osm_mgrp_t,
+				box_item);
+			status = pr_match_mgrp_attributes(sa, p_madw, p_mgrp);
+			if (status == IB_SUCCESS)
+				break;
+		}
+
 		if (status != IB_SUCCESS) {
 			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F19: "
 				"MC group attributes don't match PathRecord request\n");
diff --git a/opensm/opensm/osm_subnet.c b/opensm/opensm/osm_subnet.c
index 8d63a75..61d766a 100644
--- a/opensm/opensm/osm_subnet.c
+++ b/opensm/opensm/osm_subnet.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
@@ -430,6 +430,7 @@ void osm_subn_destroy(IN osm_subn_t * const p_subn)
 	osm_prtn_t *p_prtn, *p_next_prtn;
 	osm_mgrp_t *p_mgrp;
 	osm_infr_t *p_infr, *p_next_infr;
+	osm_mgrp_box_t *p_mgrp_box;
 
 	/* 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);
@@ -471,14 +472,19 @@ void osm_subn_destroy(IN osm_subn_t * const p_subn)
 		osm_prtn_delete(&p_prtn);
 	}
 
-	cl_fmap_remove_all(&p_subn->mgrp_mgid_tbl);
 
 	for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
 	     i++) {
-		p_mgrp = p_subn->mgroups[i];
-		p_subn->mgroups[i] = NULL;
-		if (p_mgrp)
-			osm_mgrp_delete(p_mgrp);
+		p_mgrp_box = p_subn->mboxes[i];
+		if (p_mgrp_box)
+			osm_mgrp_box_delete(p_subn, p_mgrp_box->mlid);
+	}
+
+	p_mgrp = (osm_mgrp_t*)cl_fmap_head(&p_subn->mgrp_mgid_tbl);
+	while (p_mgrp != (osm_mgrp_t*)cl_fmap_end(&p_subn->mgrp_mgid_tbl)) {
+		cl_fmap_remove_item(&p_subn->mgrp_mgid_tbl, (cl_fmap_item_t*)p_mgrp);
+		osm_mgrp_delete(p_mgrp);
+		p_mgrp = (osm_mgrp_t*)cl_fmap_head(&p_subn->mgrp_mgid_tbl);
 	}
 
 	p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list);
@@ -1655,3 +1661,18 @@ int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t *const p_opts)
 
 	return 0;
 }
+
+ib_net16_t osm_mgrp_box_get_mlid(IN struct osm_mgrp_box *p_mgrp_box)
+{
+	return (p_mgrp_box->mlid);
+}
+
+ib_net16_t osm_mgrp_box_get_mlid_by_mgid(IN osm_subn_t const *p_subn,
+					IN const ib_gid_t * const p_mgid)
+{
+	osm_mgrp_t *p_mgrp = (osm_mgrp_t*)cl_fmap_get(&p_subn->mgrp_mgid_tbl, p_mgid);
+	if (p_mgrp != (osm_mgrp_t*)cl_fmap_end(&p_subn->mgrp_mgid_tbl)) {
+		return p_mgrp->mlid;
+	}
+	return 0;
+}
-- 
1.6.3.3




More information about the general mailing list