[ofa-general] Re: [PATCH] opensm: multicast multiplexing many mgid to mlid

Slava Strebkov slavas at Voltaire.COM
Sun Jun 28 03:39:28 PDT 2009


Subject: [PATCH 3/4] Patch implements multicast multiplexing as proposed in the
 thread entitled "IPv6 and IPoIB scalability issue".
 This part (3) introduces usage of new infrastructure
 for mgid->mlid compression
 Signed-off-by: Slava Strebkov <slavas at voltaire.com>

---
 opensm/include/opensm/osm_multicast.h  |    5 +-
 opensm/include/opensm/osm_sm.h         |   23 ++-
 opensm/opensm/osm_drop_mgr.c           |   14 +-
 opensm/opensm/osm_mcast_mgr.c          |    2 +-
 opensm/opensm/osm_multicast.c          |    2 +-
 opensm/opensm/osm_qos_policy.c         |  360 ++++++++++++++++++--------------
 opensm/opensm/osm_sa.c                 |   65 ++++--
 opensm/opensm/osm_sa_mcmember_record.c |  161 ++++++++-------
 opensm/opensm/osm_sa_path_record.c     |   32 +++-
 opensm/opensm/osm_sm.c                 |   92 +++++++--
 opensm/opensm/osm_subnet.c             |   12 +-
 11 files changed, 474 insertions(+), 294 deletions(-)

diff --git a/opensm/include/opensm/osm_multicast.h b/opensm/include/opensm/osm_multicast.h
index 9f0cd96..567a989 100644
--- a/opensm/include/opensm/osm_multicast.h
+++ b/opensm/include/opensm/osm_multicast.h
@@ -331,12 +331,15 @@ osm_mgrp_t *osm_mgrp_new(IN const ib_net16_t mlid);
 *
 * SYNOPSIS
 */
-void osm_mgrp_delete(IN osm_mgrp_t * const p_mgrp);
+void osm_mgrp_delete_group(IN osm_subn_t * p_subn, IN osm_mgrp_t * const p_mgrp);
 /*
 * PARAMETERS
 *	p_mgrp
 *		[in] Pointer to an osm_mgrp_t object.
 *
+*	p_subn
+*		[in] Pointer to an osm_subn_t object.
+*
 * RETURN VALUES
 *	None.
 *
diff --git a/opensm/include/opensm/osm_sm.h b/opensm/include/opensm/osm_sm.h
index cc8321d..26530f3 100644
--- a/opensm/include/opensm/osm_sm.h
+++ b/opensm/include/opensm/osm_sm.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.
  *
@@ -61,6 +61,7 @@
 #include <opensm/osm_port.h>
 #include <opensm/osm_db.h>
 #include <opensm/osm_remote_sm.h>
+#include <opensm/osm_multicast.h>
 
 #ifdef __cplusplus
 #  define BEGIN_C_DECLS extern "C" {
@@ -101,7 +102,7 @@ BEGIN_C_DECLS
 *
 * SYNOPSIS
 */
-typedef struct osm_sm {
+    typedef struct osm_sm {
 	osm_thread_state_t thread_state;
 	unsigned signal_mask;
 	cl_spinlock_t signal_lock;
@@ -539,7 +540,7 @@ osm_resp_send(IN osm_sm_t * sm,
 ib_api_status_t
 osm_sm_mcgrp_join(IN osm_sm_t * const p_sm,
 		  IN const ib_net16_t mlid,
-		  IN const ib_net64_t port_guid);
+		  IN const ib_net64_t port_guid, IN const ib_gid_t * p_mgid);
 /*
 * PARAMETERS
 *	p_sm
@@ -551,6 +552,8 @@ osm_sm_mcgrp_join(IN osm_sm_t * const p_sm,
 *	port_guid
 *		[in] Port GUID to add to the group.
 *
+*   	p_mgid
+*		[in] MGID to add to the group holder.
 * RETURN VALUES
 *	None
 *
@@ -572,7 +575,7 @@ osm_sm_mcgrp_join(IN osm_sm_t * const p_sm,
 */
 ib_api_status_t
 osm_sm_mcgrp_leave(IN osm_sm_t * const p_sm,
-		   IN const ib_net16_t mlid, IN const ib_net64_t port_guid);
+		   IN osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid);
 /*
 * PARAMETERS
 *	p_sm
@@ -689,7 +692,7 @@ osm_sm_is_greater_than(IN const uint8_t l_priority,
 *
 * SYNOPSIS
 */
-ib_api_status_t osm_sm_state_mgr_process(IN osm_sm_t *sm,
+ib_api_status_t osm_sm_state_mgr_process(IN osm_sm_t * sm,
 					 IN osm_sm_signal_t signal);
 /*
 * PARAMETERS
@@ -718,7 +721,7 @@ ib_api_status_t osm_sm_state_mgr_process(IN osm_sm_t *sm,
 *
 * SYNOPSIS
 */
-void osm_sm_state_mgr_signal_master_is_alive(IN osm_sm_t *sm);
+void osm_sm_state_mgr_signal_master_is_alive(IN osm_sm_t * sm);
 /*
 * PARAMETERS
 *	sm
@@ -743,7 +746,7 @@ void osm_sm_state_mgr_signal_master_is_alive(IN osm_sm_t *sm);
 *
 * SYNOPSIS
 */
-ib_api_status_t osm_sm_state_mgr_check_legality(IN osm_sm_t *sm,
+ib_api_status_t osm_sm_state_mgr_check_legality(IN osm_sm_t * sm,
 						IN osm_sm_signal_t signal);
 /*
 * PARAMETERS
@@ -762,7 +765,7 @@ ib_api_status_t osm_sm_state_mgr_check_legality(IN osm_sm_t *sm,
 *	State Manager
 *********/
 
-void osm_report_sm_state(osm_sm_t *sm);
+void osm_report_sm_state(osm_sm_t * sm);
 
 /****f* OpenSM: SM State Manager/osm_send_trap144
 * NAME
@@ -773,7 +776,7 @@ void osm_report_sm_state(osm_sm_t *sm);
 *
 * SYNOPSIS
 */
-int osm_send_trap144(osm_sm_t *sm, ib_net16_t local);
+int osm_send_trap144(osm_sm_t * sm, ib_net16_t local);
 /*
 * PARAMETERS
 *	sm
@@ -787,7 +790,7 @@ int osm_send_trap144(osm_sm_t *sm, ib_net16_t local);
 *
 *********/
 
-void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority);
+void osm_set_sm_priority(osm_sm_t * sm, uint8_t priority);
 
 END_C_DECLS
 #endif				/* _OSM_SM_H_ */
diff --git a/opensm/opensm/osm_drop_mgr.c b/opensm/opensm/osm_drop_mgr.c
index c9a4f33..d92fdfc 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.
@@ -158,7 +158,6 @@ static void drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port)
 	osm_port_t *p_port_check;
 	cl_qmap_t *p_sm_guid_tbl;
 	osm_mcm_info_t *p_mcm;
-	osm_mgrp_t *p_mgrp;
 	cl_ptr_vector_t *p_port_lid_tbl;
 	uint16_t min_lid_ho;
 	uint16_t max_lid_ho;
@@ -168,6 +167,7 @@ static void drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port)
 	ib_gid_t port_gid;
 	ib_mad_notice_attr_t notice;
 	ib_api_status_t status;
+	osm_mgrp_holder_t *p_osm_mgrp_holder;
 
 	OSM_LOG_ENTER(sm->p_log);
 
@@ -212,10 +212,12 @@ static void drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port)
 
 	p_mcm = (osm_mcm_info_t *) cl_qlist_remove_head(&p_port->mcm_list);
 	while (p_mcm != (osm_mcm_info_t *) cl_qlist_end(&p_port->mcm_list)) {
-		p_mgrp = osm_get_mgrp_by_mlid(sm->p_subn, p_mcm->mlid);
-		if (p_mgrp) {
-			osm_mgrp_delete_port(sm->p_subn, sm->p_log,
-					     p_mgrp, p_port->guid);
+		p_osm_mgrp_holder =
+		    osm_get_mgrp_holder_by_mlid(sm->p_subn, p_mcm->mlid);
+		if (p_osm_mgrp_holder) {
+			osm_mgrp_holder_remove_port(sm->p_subn, sm->p_log,
+						    p_osm_mgrp_holder,
+						    p_port->guid);
 			osm_mcm_info_delete((osm_mcm_info_t *) p_mcm);
 		}
 		p_mcm =
diff --git a/opensm/opensm/osm_mcast_mgr.c b/opensm/opensm/osm_mcast_mgr.c
index de0a8a5..e16c2e7 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-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.
diff --git a/opensm/opensm/osm_multicast.c b/opensm/opensm/osm_multicast.c
index d2a19ea..e2e588c 100644
--- a/opensm/opensm/osm_multicast.c
+++ b/opensm/opensm/osm_multicast.c
@@ -41,7 +41,7 @@
 #if HAVE_CONFIG_H
 #  include <config.h>
 #endif				/* HAVE_CONFIG_H */
-
+#include <arpa/inet.h>
 #include <stdlib.h>
 #include <string.h>
 #include <opensm/osm_sa.h>
diff --git a/opensm/opensm/osm_qos_policy.c b/opensm/opensm/osm_qos_policy.c
index 094fef2..07b05f5 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.
@@ -59,11 +59,10 @@ extern osm_qos_level_t __default_simple_qos_level;
 /***************************************************
  ***************************************************/
 
-static void
-__build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)
+static void __build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)
 {
-	osm_node_t * p_node;
-	cl_qmap_t  * p_node_guid_tbl = &p_qos_policy->p_subn->node_guid_tbl;
+	osm_node_t *p_node;
+	cl_qmap_t *p_node_guid_tbl = &p_qos_policy->p_subn->node_guid_tbl;
 
 	p_qos_policy->p_node_hash = st_init_strtable();
 	CL_ASSERT(p_qos_policy->p_node_hash);
@@ -75,10 +74,10 @@ __build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)
 	     p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl);
 	     p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) {
 		if (!st_lookup(p_qos_policy->p_node_hash,
-			      (st_data_t)p_node->print_desc, NULL))
+			       (st_data_t) p_node->print_desc, NULL))
 			st_insert(p_qos_policy->p_node_hash,
-				  (st_data_t)p_node->print_desc,
-				  (st_data_t)p_node);
+				  (st_data_t) p_node->print_desc,
+				  (st_data_t) p_node);
 	}
 }
 
@@ -87,7 +86,7 @@ __build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)
 
 static boolean_t
 __is_num_in_range_arr(uint64_t ** range_arr,
-		  unsigned range_arr_len, uint64_t num)
+		      unsigned range_arr_len, uint64_t num)
 {
 	unsigned ind_1 = 0;
 	unsigned ind_2 = range_arr_len - 1;
@@ -97,22 +96,23 @@ __is_num_in_range_arr(uint64_t ** range_arr,
 		return FALSE;
 
 	while (ind_1 <= ind_2) {
-	    if (num < range_arr[ind_1][0] || num > range_arr[ind_2][1])
-		return FALSE;
-	    else if (num <= range_arr[ind_1][1] || num >= range_arr[ind_2][0])
-		return TRUE;
-
-	    ind_mid = ind_1 + (ind_2 - ind_1 + 1)/2;
-
-	    if (num < range_arr[ind_mid][0])
-		ind_2 = ind_mid;
-	    else if (num > range_arr[ind_mid][1])
-		ind_1 = ind_mid;
-	    else
-		return TRUE;
-
-	    ind_1++;
-	    ind_2--;
+		if (num < range_arr[ind_1][0] || num > range_arr[ind_2][1])
+			return FALSE;
+		else if (num <= range_arr[ind_1][1]
+			 || num >= range_arr[ind_2][0])
+			return TRUE;
+
+		ind_mid = ind_1 + (ind_2 - ind_1 + 1) / 2;
+
+		if (num < range_arr[ind_mid][0])
+			ind_2 = ind_mid;
+		else if (num > range_arr[ind_mid][1])
+			ind_1 = ind_mid;
+		else
+			return TRUE;
+
+		ind_1++;
+		ind_2--;
 	}
 
 	return FALSE;
@@ -130,10 +130,9 @@ static void __free_single_element(void *p_element, void *context)
 /***************************************************
  ***************************************************/
 
-osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t *p_physp)
+osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t * p_physp)
 {
-	osm_qos_port_t *p =
-	    (osm_qos_port_t *) malloc(sizeof(osm_qos_port_t));
+	osm_qos_port_t *p = (osm_qos_port_t *) malloc(sizeof(osm_qos_port_t));
 	if (!p)
 		return NULL;
 	memset(p, 0, sizeof(osm_qos_port_t));
@@ -163,8 +162,8 @@ osm_qos_port_group_t *osm_qos_policy_port_group_create()
 
 void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p)
 {
-	osm_qos_port_t * p_port;
-	osm_qos_port_t * p_old_port;
+	osm_qos_port_t *p_port;
+	osm_qos_port_t *p_old_port;
 
 	if (!p)
 		return;
@@ -175,8 +174,7 @@ void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p)
 		free(p->use);
 
 	p_port = (osm_qos_port_t *) cl_qmap_head(&p->port_map);
-	while (p_port != (osm_qos_port_t *) cl_qmap_end(&p->port_map))
-	{
+	while (p_port != (osm_qos_port_t *) cl_qmap_end(&p->port_map)) {
 		p_old_port = p_port;
 		p_port = (osm_qos_port_t *) cl_qmap_next(&p_port->map_item);
 		free(p_old_port);
@@ -424,9 +422,10 @@ void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p)
 /***************************************************
  ***************************************************/
 
-osm_qos_policy_t * osm_qos_policy_create(osm_subn_t * p_subn)
+osm_qos_policy_t *osm_qos_policy_create(osm_subn_t * p_subn)
 {
-	osm_qos_policy_t * p_qos_policy = (osm_qos_policy_t *)malloc(sizeof(osm_qos_policy_t));
+	osm_qos_policy_t *p_qos_policy =
+	    (osm_qos_policy_t *) malloc(sizeof(osm_qos_policy_t));
 	if (!p_qos_policy)
 		return NULL;
 
@@ -544,8 +543,8 @@ __qos_policy_is_port_in_group(osm_subn_t * p_subn,
 
 	/* check whether this port's type matches any of group's types */
 
-	if ( p_port_group->node_types &
-	     (((uint8_t)1)<<osm_node_get_type(p_node)) )
+	if (p_port_group->node_types &
+	    (((uint8_t) 1) << osm_node_get_type(p_node)))
 		return TRUE;
 
 	/* check whether this port's guid is in group's port map */
@@ -585,24 +584,33 @@ __qos_policy_is_port_in_group_list(const osm_qos_policy_t * p_qos_policy,
 /***************************************************
  ***************************************************/
 
-static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(
-			 const osm_qos_policy_t * p_qos_policy,
-			 uint64_t service_id,
-			 uint16_t qos_class,
-			 uint16_t pkey,
-			 const osm_physp_t * p_src_physp,
-			 const osm_physp_t * p_dest_physp,
-			 ib_net64_t comp_mask)
+static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(const
+								   osm_qos_policy_t
+								   *
+								   p_qos_policy,
+								   uint64_t
+								   service_id,
+								   uint16_t
+								   qos_class,
+								   uint16_t
+								   pkey,
+								   const
+								   osm_physp_t *
+								   p_src_physp,
+								   const
+								   osm_physp_t *
+								   p_dest_physp,
+								   ib_net64_t
+								   comp_mask)
 {
 	osm_qos_match_rule_t *p_qos_match_rule = NULL;
 	cl_list_iterator_t list_iterator;
-	osm_log_t * p_log = &p_qos_policy->p_subn->p_osm->log;
+	osm_log_t *p_log = &p_qos_policy->p_subn->p_osm->log;
 
 	boolean_t matched_by_sguid = FALSE,
-		  matched_by_dguid = FALSE,
-		  matched_by_class = FALSE,
-		  matched_by_sid = FALSE,
-		  matched_by_pkey = FALSE;
+	    matched_by_dguid = FALSE,
+	    matched_by_class = FALSE,
+	    matched_by_sid = FALSE, matched_by_pkey = FALSE;
 
 	if (!cl_list_count(&p_qos_policy->qos_match_rules))
 		return NULL;
@@ -698,8 +706,7 @@ static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(
 
 			if (!__is_num_in_range_arr
 			    (p_qos_match_rule->pkey_range_arr,
-			     p_qos_match_rule->pkey_range_len,
-			     pkey & 0x7FFF)) {
+			     p_qos_match_rule->pkey_range_len, pkey & 0x7FFF)) {
 				list_iterator = cl_list_next(list_iterator);
 				continue;
 			}
@@ -717,15 +724,14 @@ static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(
 		OSM_LOG(p_log, OSM_LOG_DEBUG,
 			"request matched rule (%s) by:%s%s%s%s%s\n",
 			(p_qos_match_rule->use) ?
-				p_qos_match_rule->use : "no description",
+			p_qos_match_rule->use : "no description",
 			(matched_by_sguid) ? " SGUID" : "",
 			(matched_by_dguid) ? " DGUID" : "",
 			(matched_by_class) ? " QoS_Class" : "",
-			(matched_by_sid)   ? " ServiceID" : "",
-			(matched_by_pkey)  ? " PKey" : "");
+			(matched_by_sid) ? " ServiceID" : "",
+			(matched_by_pkey) ? " PKey" : "");
 	else
-		OSM_LOG(p_log, OSM_LOG_DEBUG,
-			"request not matched any rule\n");
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "request not matched any rule\n");
 
 	OSM_LOG_EXIT(p_log);
 	return p_qos_match_rule;
@@ -734,9 +740,10 @@ static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(
 /***************************************************
  ***************************************************/
 
-static osm_qos_level_t *__qos_policy_get_qos_level_by_name(
-		const osm_qos_policy_t * p_qos_policy,
-		char *name)
+static osm_qos_level_t *__qos_policy_get_qos_level_by_name(const
+							   osm_qos_policy_t *
+							   p_qos_policy,
+							   char *name)
 {
 	osm_qos_level_t *p_qos_level = NULL;
 	cl_list_iterator_t list_iterator;
@@ -760,9 +767,11 @@ static osm_qos_level_t *__qos_policy_get_qos_level_by_name(
 /***************************************************
  ***************************************************/
 
-static osm_qos_port_group_t *__qos_policy_get_port_group_by_name(
-		const osm_qos_policy_t * p_qos_policy,
-		const char *const name)
+static osm_qos_port_group_t *__qos_policy_get_port_group_by_name(const
+								 osm_qos_policy_t
+								 * p_qos_policy,
+								 const char
+								 *const name)
 {
 	osm_qos_port_group_t *p_port_group = NULL;
 	cl_list_iterator_t list_iterator;
@@ -787,15 +796,16 @@ static osm_qos_port_group_t *__qos_policy_get_port_group_by_name(
 /***************************************************
  ***************************************************/
 
-static void __qos_policy_validate_pkey(
-			osm_qos_policy_t * p_qos_policy,
-			osm_qos_match_rule_t * p_qos_match_rule,
-			osm_prtn_t * p_prtn)
+static void __qos_policy_validate_pkey(osm_qos_policy_t * p_qos_policy,
+				       osm_qos_match_rule_t * p_qos_match_rule,
+				       osm_prtn_t * p_prtn)
 {
 	uint8_t sl;
 	uint32_t flow;
 	uint8_t hop;
-	osm_mgrp_t * p_mgrp;
+	osm_mgrp_t *p_mgrp;
+	osm_mgrp_holder_t *p_mgrp_holder;
+	cl_fmap_item_t *p_fitem;
 
 	if (!p_qos_policy || !p_qos_match_rule || !p_prtn)
 		return;
@@ -812,43 +822,49 @@ static void __qos_policy_validate_pkey(
 		p_qos_match_rule->p_qos_level->sl);
 	p_prtn->sl = p_qos_match_rule->p_qos_level->sl;
 
-
 	/* If this partition is an IPoIB partition, there should
 	   be a matching MCast group. Fix this group's SL too */
 
 	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_holder =
+	    osm_get_mgrp_holder_by_mlid(p_qos_policy->p_subn, p_prtn->mlid);
+	if (!p_mgrp_holder) {
 		OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR,
-			"ERR AC16: MCast group for partition with "
-			"pkey 0x%04X not found\n",
-			cl_ntoh16(p_prtn->pkey));
+			"ERR AC16: MCast mgrp_holder 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 =
-			ib_member_set_sl_flow_hop(p_prtn->sl, flow, hop);
+	p_fitem = cl_fmap_head(&p_mgrp_holder->mgrp_map);
+	while (p_fitem != cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+		p_mgrp =
+		    (osm_mgrp_t *) PARENT_STRUCT(p_fitem, osm_mgrp_t,
+						 mgid_item);
+		p_fitem = cl_fmap_next(p_fitem);
+
+		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);
+		}
 	}
 }
 
 /***************************************************
  ***************************************************/
 
-int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
-			    osm_log_t *p_log)
+int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy, osm_log_t * p_log)
 {
 	cl_list_iterator_t match_rules_list_iterator;
 	cl_list_iterator_t list_iterator;
@@ -859,22 +875,23 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 	int res = 0;
 	uint64_t pkey_64;
 	ib_net16_t pkey;
-	osm_prtn_t * p_prtn;
+	osm_prtn_t *p_prtn;
 
 	OSM_LOG_ENTER(p_log);
 
 	/* set default qos level */
 
 	p_qos_policy->p_default_qos_level =
-	    __qos_policy_get_qos_level_by_name(p_qos_policy, OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
+	    __qos_policy_get_qos_level_by_name(p_qos_policy,
+					       OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
 	if (!p_qos_policy->p_default_qos_level) {
 		/* There's no default QoS level in the usual qos-level section.
 		   Check whether the 'simple' default QoS level that can be
 		   defined in the qos-ulp section exists */
 		if (__default_simple_qos_level.sl_set) {
-			p_qos_policy->p_default_qos_level = &__default_simple_qos_level;
-		}
-		else {
+			p_qos_policy->p_default_qos_level =
+			    &__default_simple_qos_level;
+		} else {
 			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC10: "
 				"Default qos-level (%s) not defined.\n",
 				OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
@@ -891,8 +908,7 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 	    cl_list_head(&p_qos_policy->qos_match_rules);
 	while (match_rules_list_iterator !=
 	       cl_list_end(&p_qos_policy->qos_match_rules)) {
-		p_qos_match_rule =
-		    (osm_qos_match_rule_t *)
+		p_qos_match_rule = (osm_qos_match_rule_t *)
 		    cl_list_obj(match_rules_list_iterator);
 		CL_ASSERT(p_qos_match_rule);
 
@@ -900,8 +916,9 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 
 		if (!p_qos_match_rule->p_qos_level)
 			p_qos_match_rule->p_qos_level =
-				__qos_policy_get_qos_level_by_name(p_qos_policy,
-					       p_qos_match_rule->qos_level_name);
+			    __qos_policy_get_qos_level_by_name(p_qos_policy,
+							       p_qos_match_rule->
+							       qos_level_name);
 
 		if (!p_qos_match_rule->p_qos_level) {
 			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC11: "
@@ -922,9 +939,11 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 				CL_ASSERT(str);
 
 				p_port_group =
-				    __qos_policy_get_port_group_by_name(p_qos_policy, str);
+				    __qos_policy_get_port_group_by_name
+				    (p_qos_policy, str);
 				if (!p_port_group) {
-					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC12: "
+					OSM_LOG(p_log, OSM_LOG_ERROR,
+						"ERR AC12: "
 						"qos-match-rule num %u: source port-group '%s' not found\n",
 						i, str);
 					res = 1;
@@ -951,9 +970,11 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 				CL_ASSERT(str);
 
 				p_port_group =
-				    __qos_policy_get_port_group_by_name(p_qos_policy,str);
+				    __qos_policy_get_port_group_by_name
+				    (p_qos_policy, str);
 				if (!p_port_group) {
-					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC13: "
+					OSM_LOG(p_log, OSM_LOG_ERROR,
+						"ERR AC13: "
 						"qos-match-rule num %u: destination port-group '%s' not found\n",
 						i, str);
 					res = 1;
@@ -977,24 +998,30 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
 		 */
 
 		for (j = 0; j < p_qos_match_rule->pkey_range_len; j++) {
-			for ( pkey_64 = p_qos_match_rule->pkey_range_arr[j][0];
-			      pkey_64 <= p_qos_match_rule->pkey_range_arr[j][1];
-			      pkey_64++) {
-                                pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
-				p_prtn = (osm_prtn_t *)cl_qmap_get(
-					&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
-
-				if (p_prtn == (osm_prtn_t *)cl_qmap_end(
-					&p_qos_policy->p_subn->prtn_pkey_tbl))
+			for (pkey_64 = p_qos_match_rule->pkey_range_arr[j][0];
+			     pkey_64 <= p_qos_match_rule->pkey_range_arr[j][1];
+			     pkey_64++) {
+				pkey = cl_hton16((uint16_t) (pkey_64 & 0x7fff));
+				p_prtn =
+				    (osm_prtn_t *) cl_qmap_get(&p_qos_policy->
+							       p_subn->
+							       prtn_pkey_tbl,
+							       pkey);
+
+				if (p_prtn ==
+				    (osm_prtn_t *) cl_qmap_end(&p_qos_policy->
+							       p_subn->
+							       prtn_pkey_tbl))
 					/* partition for this pkey not found */
-					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC14: "
+					OSM_LOG(p_log, OSM_LOG_ERROR,
+						"ERR AC14: "
 						"pkey 0x%04X in match rule - "
 						"partition doesn't exist\n",
 						cl_ntoh16(pkey));
 				else
 					__qos_policy_validate_pkey(p_qos_policy,
-							p_qos_match_rule,
-							p_prtn);
+								   p_qos_match_rule,
+								   p_prtn);
 			}
 		}
 
@@ -1013,53 +1040,70 @@ Exit:
 /***************************************************
  ***************************************************/
 
-static osm_qos_level_t * __qos_policy_get_qos_level_by_params(
-	IN const osm_qos_policy_t * p_qos_policy,
-	IN const osm_physp_t * p_src_physp,
-	IN const osm_physp_t * p_dest_physp,
-	IN uint64_t service_id,
-	IN uint16_t qos_class,
-	IN uint16_t pkey,
-	IN ib_net64_t comp_mask)
+static osm_qos_level_t *__qos_policy_get_qos_level_by_params(IN const
+							     osm_qos_policy_t *
+							     p_qos_policy,
+							     IN const
+							     osm_physp_t *
+							     p_src_physp,
+							     IN const
+							     osm_physp_t *
+							     p_dest_physp,
+							     IN uint64_t
+							     service_id,
+							     IN uint16_t
+							     qos_class,
+							     IN uint16_t pkey,
+							     IN ib_net64_t
+							     comp_mask)
 {
 	osm_qos_match_rule_t *p_qos_match_rule = NULL;
 
 	if (!p_qos_policy)
 		return NULL;
 
-	p_qos_match_rule = __qos_policy_get_match_rule_by_params(
-		p_qos_policy, service_id, qos_class, pkey,
-		p_src_physp, p_dest_physp, comp_mask);
+	p_qos_match_rule =
+	    __qos_policy_get_match_rule_by_params(p_qos_policy, service_id,
+						  qos_class, pkey, p_src_physp,
+						  p_dest_physp, comp_mask);
 
 	return p_qos_match_rule ? p_qos_match_rule->p_qos_level :
-		p_qos_policy->p_default_qos_level;
+	    p_qos_policy->p_default_qos_level;
 }				/* __qos_policy_get_qos_level_by_params() */
 
 /***************************************************
  ***************************************************/
 
-osm_qos_level_t * osm_qos_policy_get_qos_level_by_pr(
-	IN const osm_qos_policy_t * p_qos_policy,
-	IN const ib_path_rec_t * p_pr,
-	IN const osm_physp_t * p_src_physp,
-	IN const osm_physp_t * p_dest_physp,
-	IN ib_net64_t comp_mask)
+osm_qos_level_t *osm_qos_policy_get_qos_level_by_pr(IN const osm_qos_policy_t *
+						    p_qos_policy,
+						    IN const ib_path_rec_t *
+						    p_pr,
+						    IN const osm_physp_t *
+						    p_src_physp,
+						    IN const osm_physp_t *
+						    p_dest_physp,
+						    IN ib_net64_t comp_mask)
 {
-	return __qos_policy_get_qos_level_by_params(
-		p_qos_policy, p_src_physp, p_dest_physp,
-		cl_ntoh64(p_pr->service_id), ib_path_rec_qos_class(p_pr),
-		cl_ntoh16(p_pr->pkey), comp_mask);
+	return __qos_policy_get_qos_level_by_params(p_qos_policy, p_src_physp,
+						    p_dest_physp,
+						    cl_ntoh64(p_pr->service_id),
+						    ib_path_rec_qos_class(p_pr),
+						    cl_ntoh16(p_pr->pkey),
+						    comp_mask);
 }
 
 /***************************************************
  ***************************************************/
 
-osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr(
-	IN const osm_qos_policy_t * p_qos_policy,
-	IN const ib_multipath_rec_t * p_mpr,
-	IN const osm_physp_t * p_src_physp,
-	IN const osm_physp_t * p_dest_physp,
-	IN ib_net64_t comp_mask)
+osm_qos_level_t *osm_qos_policy_get_qos_level_by_mpr(IN const osm_qos_policy_t *
+						     p_qos_policy,
+						     IN const ib_multipath_rec_t
+						     * p_mpr,
+						     IN const osm_physp_t *
+						     p_src_physp,
+						     IN const osm_physp_t *
+						     p_dest_physp,
+						     IN ib_net64_t comp_mask)
 {
 	ib_net64_t pr_comp_mask = 0;
 
@@ -1071,20 +1115,24 @@ osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr(
 	 * compmask. Note that only relevant bits are set.
 	 */
 	pr_comp_mask =
-		((comp_mask & IB_MPR_COMPMASK_QOS_CLASS) ?
-		 IB_PR_COMPMASK_QOS_CLASS : 0) |
-		((comp_mask & IB_MPR_COMPMASK_PKEY) ?
-		 IB_PR_COMPMASK_PKEY : 0) |
-		((comp_mask & IB_MPR_COMPMASK_SERVICEID_MSB) ?
-		 IB_PR_COMPMASK_SERVICEID_MSB : 0) |
-		((comp_mask & IB_MPR_COMPMASK_SERVICEID_LSB) ?
-		 IB_PR_COMPMASK_SERVICEID_LSB : 0);
-
-	return __qos_policy_get_qos_level_by_params(
-		p_qos_policy, p_src_physp, p_dest_physp,
-		cl_ntoh64(ib_multipath_rec_service_id(p_mpr)),
-		ib_multipath_rec_qos_class(p_mpr),
-		cl_ntoh16(p_mpr->pkey), pr_comp_mask);
+	    ((comp_mask & IB_MPR_COMPMASK_QOS_CLASS) ?
+	     IB_PR_COMPMASK_QOS_CLASS : 0) |
+	    ((comp_mask & IB_MPR_COMPMASK_PKEY) ?
+	     IB_PR_COMPMASK_PKEY : 0) |
+	    ((comp_mask & IB_MPR_COMPMASK_SERVICEID_MSB) ?
+	     IB_PR_COMPMASK_SERVICEID_MSB : 0) |
+	    ((comp_mask & IB_MPR_COMPMASK_SERVICEID_LSB) ?
+	     IB_PR_COMPMASK_SERVICEID_LSB : 0);
+
+	return __qos_policy_get_qos_level_by_params(p_qos_policy, p_src_physp,
+						    p_dest_physp,
+						    cl_ntoh64
+						    (ib_multipath_rec_service_id
+						     (p_mpr)),
+						    ib_multipath_rec_qos_class
+						    (p_mpr),
+						    cl_ntoh16(p_mpr->pkey),
+						    pr_comp_mask);
 }
 
 /***************************************************
diff --git a/opensm/opensm/osm_sa.c b/opensm/opensm/osm_sa.c
index fcc3f27..0c24a49 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.
@@ -52,6 +52,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <complib/cl_qmap.h>
+#include <complib/cl_fleximap.h>
 #include <complib/cl_passivelock.h>
 #include <complib/cl_debug.h>
 #include <iba/ib_types.h>
@@ -317,7 +318,7 @@ Exit:
 	return (status);
 }
 
-ib_api_status_t osm_sa_send(osm_sa_t *sa,
+ib_api_status_t osm_sa_send(osm_sa_t * sa,
 			    IN osm_madw_t * const p_madw,
 			    IN boolean_t const resp_expected)
 {
@@ -397,8 +398,8 @@ Exit:
 	OSM_LOG_EXIT(sa->p_log);
 }
 
-void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
-		    cl_qlist_t *list)
+void osm_sa_respond(osm_sa_t * sa, osm_madw_t * madw, size_t attr_size,
+		    cl_qlist_t * list)
 {
 	struct item_data {
 		cl_list_item_t list;
@@ -422,13 +423,13 @@ void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
 	 */
 	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
-			"Got %u records for SubnAdmGet(%s) comp_mask 0x%016" PRIx64 "\n",
-			num_rec, ib_get_sa_attr_str(sa_mad->attr_id),
+			"Got %u records for SubnAdmGet(%s) comp_mask 0x%016"
+			PRIx64 "\n", num_rec,
+			ib_get_sa_attr_str(sa_mad->attr_id),
 			cl_ntoh64(sa_mad->comp_mask));
 		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
 		goto Exit;
 	}
-
 #ifndef VENDOR_RMPP_SUPPORT
 	trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
 	if (trim_num_rec < num_rec) {
@@ -564,7 +565,7 @@ static void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt)
 		p_mcm_port->scope_state, p_mcm_port->proxy_join);
 }
 
-static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt)
+static void sa_dump_one_mgrp(osm_mgrp_t * p_mgrp, void *cxt)
 {
 	struct opensm_dump_context dump_context;
 	osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
@@ -706,6 +707,8 @@ static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
 {
 	struct opensm_dump_context dump_context;
 	osm_mgrp_t *p_mgrp;
+	cl_fmap_item_t *p_fitem;
+	osm_mgrp_holder_t *p_mgrp_holder;
 	int i;
 
 	dump_context.p_osm = p_osm;
@@ -714,9 +717,17 @@ static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
 	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)
+		p_mgrp_holder = p_osm->subn.mgroup_holders[i];
+		if (!p_mgrp_holder)
+			continue;
+		p_fitem = cl_fmap_head(&p_mgrp_holder->mgrp_map);
+		while (p_fitem != cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+			p_mgrp =
+			    (osm_mgrp_t *) PARENT_STRUCT(p_fitem, osm_mgrp_t,
+							 mgid_item);
 			sa_dump_one_mgrp(p_mgrp, &dump_context);
+			p_fitem = cl_fmap_next(&p_mgrp->mgid_item);
+		}
 	}
 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform\n");
 	cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
@@ -740,25 +751,35 @@ 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;
-
+	cl_fmap_item_t *p_fitem;
+	osm_mgrp_holder_t *p_mgrp_holder;
+	ib_gid_t common_mgid;
+	osm_mgrp_t *p_mgrp = NULL;
 	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))) {
+	p_mgrp_holder = osm_get_mgrp_holder_by_mlid(&p_osm->subn, mlid);
+	if (p_mgrp_holder) {
+		p_fitem =
+		    cl_fmap_get(&p_mgrp_holder->mgrp_map, &p_mcm_rec->mgid);
+		if (p_fitem != cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
 			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;
-		goto _out;
-	}
 
+		osm_mgrp_holder_prepare_common_mgid(&p_mcm_rec->mgid,
+						    &common_mgid);
+		if (memcmp
+		    (&p_mgrp_holder->common_mgid, &common_mgid,
+		     sizeof(ib_gid_t))) {
+			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;
+			goto _out;
+		}
+	}
 	comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
 	    | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
 	if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa,
diff --git a/opensm/opensm/osm_sa_mcmember_record.c b/opensm/opensm/osm_sa_mcmember_record.c
index 5543221..23c5107 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.
@@ -63,6 +63,7 @@
 #include <opensm/osm_pkey.h>
 #include <opensm/osm_inform.h>
 #include <opensm/osm_sa.h>
+#include <opensm/osm_mcm_info.h>
 
 #define JOIN_MC_COMP_MASK (IB_MCR_COMPMASK_MGID | \
 				IB_MCR_COMPMASK_PORT_GID | \
@@ -121,13 +122,14 @@ 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_holder_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++) {
-		osm_mgrp_t *p_mgrp = sa->p_subn->mgroups[i];
-		if (!p_mgrp || p_mgrp->to_be_deleted)
+		osm_mgrp_holder_t *p_mgrp_holder =
+		    (osm_mgrp_holder_t *) sa->p_subn->mgroup_holders[i];
+		if (!p_mgrp_holder || p_mgrp_holder->to_be_deleted)
 			return cl_hton16(i + IB_LID_MCAST_START_HO);
 	}
 
@@ -141,14 +143,21 @@ static ib_net16_t get_new_mlid(osm_sa_t * sa, ib_net16_t requested_mlid)
  we silently drop it. Since it was an intermediate group no need to
  re-route it.
 **********************************************************************/
-static void cleanup_mgrp(IN osm_sa_t * sa, osm_mgrp_t * mgrp)
+static void cleanup_mgrp(IN osm_sa_t * sa, osm_mgrp_t * p_mgrp)
 {
 	/* Remove MGRP only if osm_mcm_port_t count is 0 and
 	   not a well known group */
-	if (cl_is_qmap_empty(&mgrp->mcm_port_tbl) && !mgrp->well_known) {
-		sa->p_subn->mgroups[cl_ntoh16(mgrp->mlid) -
-				    IB_LID_MCAST_START_HO] = NULL;
-		osm_mgrp_delete(mgrp);
+	char gid_str[INET6_ADDRSTRLEN];
+	if (cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) && !p_mgrp->well_known) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"mgrp mgid %s will be deleted\n", inet_ntop(AF_INET6,
+								    p_mgrp->
+								    mcmember_rec.
+								    mgid.raw,
+								    gid_str,
+								    sizeof
+								    (gid_str)));
+		osm_mgrp_delete_group(sa->sm->p_subn, p_mgrp);
 	}
 }
 
@@ -202,7 +211,6 @@ static ib_api_status_t add_new_mgrp_port(osm_sa_t * sa, IN osm_mgrp_t * p_mgrp,
 
 		return IB_INSUFFICIENT_MEMORY;
 	}
-
 	return IB_SUCCESS;
 }
 
@@ -806,11 +814,12 @@ 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;
+	char gid_str[INET6_ADDRSTRLEN];
 	ib_gid_t *p_mgid;
-	osm_mgrp_t *p_prev_mgrp;
+	osm_mgrp_holder_t *p_mgrp_holder;
 	ib_api_status_t status = IB_SUCCESS;
 	ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec;	/* copy for modifications */
 
@@ -823,7 +832,7 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 			zero_mgid = 0;
 			break;
 		}
-
+	p_mgid = &(mcm_rec.mgid);
 	/*
 	   we allocate a new mlid number before we might use it
 	   for MGID ...
@@ -843,8 +852,6 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 	/* we need to create the new MGID if it was not defined */
 	if (zero_mgid) {
 		/* create a new MGID */
-		char gid_str[INET6_ADDRSTRLEN];
-
 		/* use the given scope state only if requested! */
 		if (comp_mask & IB_MCR_COMPMASK_SCOPE)
 			ib_member_get_scope_state(p_recvd_mcmember_rec->
@@ -888,6 +895,13 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 		goto Exit;
 	}
 
+	if (0 != (existed_mlid = osm_mgrp_holder_get_mlid_by_mgid(sa, p_mgid))) {
+		mlid = existed_mlid;
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"found existed  mlid  0x%04x for mgid %s\n",
+			cl_ntoh16(mlid), inet_ntop(AF_INET6, p_mgid->raw,
+						   gid_str, sizeof gid_str));
+	}
 	/* create a new MC Group */
 	*pp_mgrp = osm_mgrp_new(mlid);
 	if (*pp_mgrp == NULL) {
@@ -915,17 +929,21 @@ ib_api_status_t osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
 	/* since we might have an old group by that mlid
 	   one whose deletion was delayed for an idle time
 	   we need to deallocate it first */
-	p_prev_mgrp = osm_get_mgrp_by_mlid(sa->p_subn, mlid);
-	if (p_prev_mgrp) {
+	p_mgrp_holder = osm_get_mgrp_holder_by_mlid(sa->p_subn, mlid);
+	if (!p_mgrp_holder) {
 		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
-			"Found previous group for mlid:0x%04x - "
-			"Destroying it first\n", cl_ntoh16(mlid));
-		sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] =
-		    NULL;
-		osm_mgrp_delete(p_prev_mgrp);
+			"Creating new mgrp holder  for mlid:0x%04x\n",
+			cl_ntoh16(mlid));
+		p_mgrp_holder = osm_mgrp_holder_new(sa->p_subn, p_mgid, mlid);
 	}
-
-	sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = *pp_mgrp;
+	if (!p_mgrp_holder) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B08: "
+			"osm_mgrp_holder_new failed\n");
+		free_mlid(sa, mlid);
+		status = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+	osm_mgrp_holder_add_mgrp(p_mgrp_holder, *pp_mgrp, sa->p_log);
 
 Exit:
 	OSM_LOG_EXIT(sa->p_log);
@@ -934,56 +952,47 @@ Exit:
 
 /**********************************************************************
  *********************************************************************/
-static unsigned match_mgrp_by_mgid(IN osm_mgrp_t * p_mgrp, ib_gid_t * mgid)
-{
-	/* ignore groups marked for deletion */
-	if (p_mgrp->to_be_deleted ||
-	    memcmp(&p_mgrp->mcmember_rec.mgid, mgid, sizeof(ib_gid_t)))
-		return 0;
-	else
-		return 1;
-}
-
-/**********************************************************************
- **********************************************************************/
-#define PREFIX_MASK CL_HTON64(0xff10ffff0000ffffULL)
-#define PREFIX_SIGNATURE CL_HTON64(0xff10601b00000000ULL)
-#define INT_ID_MASK CL_HTON64(0xfffffff1ff000000ULL)
-#define INT_ID_SIGNATURE CL_HTON64(0x00000001ff000000ULL)
-
-/* Special Case IPv6 Solicited Node Multicast (SNM) addresses */
-/* 0xff1Z601bXXXX0000 : 0x00000001ffYYYYYY */
-/* Where Z is the scope, XXXX is the P_Key, and
- * YYYYYY is the last 24 bits of the port guid */
-static unsigned match_and_update_ipv6_snm_mgid(ib_gid_t * mgid)
+static osm_mgrp_t *match_mgrp_by_mgid(IN osm_mgrp_holder_t * p_mgrp_holder,
+				      ib_gid_t * p_mgid)
 {
-	if ((mgid->unicast.prefix & PREFIX_MASK) == PREFIX_SIGNATURE &&
-	    (mgid->unicast.interface_id & INT_ID_MASK) == INT_ID_SIGNATURE) {
-		mgid->unicast.prefix &= PREFIX_MASK;
-		mgid->unicast.interface_id &= INT_ID_MASK;
-		return 1;
-	}
-	return 0;
+	osm_mgrp_t *p_mgrp;
+	ib_gid_t common_mgid;
+	cl_fmap_item_t *p_fitem;
+
+	osm_mgrp_holder_prepare_common_mgid(p_mgid, &common_mgid);
+
+	if (memcmp(&p_mgrp_holder->common_mgid, &common_mgid, sizeof(ib_gid_t)))
+		return NULL;
+	p_fitem = cl_fmap_get(&p_mgrp_holder->mgrp_map, p_mgid);
+	if (p_fitem != cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+		p_mgrp = (osm_mgrp_t *) PARENT_STRUCT(p_fitem, osm_mgrp_t,
+						      mgid_item);
+		/* ignore groups marked for deletion */
+		if (p_mgrp->to_be_deleted)
+			p_mgrp = NULL;
+	} else
+		p_mgrp = NULL;
+	return p_mgrp;;
 }
 
 osm_mgrp_t *osm_get_mgrp_by_mgid(IN osm_sa_t * sa, IN ib_gid_t * p_mgid)
 {
 	int i;
-
-	if (sa->p_subn->opt.consolidate_ipv6_snm_req &&
-	    match_and_update_ipv6_snm_mgid(p_mgid)) {
-		char gid_str[INET6_ADDRSTRLEN];
-		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
-			"Special Case Solicited Node Mcast Join for MGID %s\n",
-			inet_ntop(AF_INET6, p_mgid->raw, gid_str,
-				  sizeof gid_str));
-	}
-
+	osm_mgrp_t *p_mgrp;
 	for (i = 0; i <= sa->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
-	     i++)
-		if (sa->p_subn->mgroups[i] &&
-		    match_mgrp_by_mgid(sa->p_subn->mgroups[i], p_mgid))
-			return sa->p_subn->mgroups[i];
+	     i++) {
+		if (sa->p_subn->mgroup_holders[i] &&
+		    (p_mgrp =
+		     match_mgrp_by_mgid(sa->p_subn->mgroup_holders[i],
+					p_mgid))) {
+			char gid_str[INET6_ADDRSTRLEN];
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Found mgroup for MGID %s\n",
+				inet_ntop(AF_INET6, p_mgid->raw, gid_str,
+					  sizeof gid_str));
+			return p_mgrp;
+		}
+	}
 
 	return NULL;
 }
@@ -1080,7 +1089,7 @@ static void mcmr_rcv_leave_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 	CL_PLOCK_RELEASE(sa->p_lock);
 
 	/* we can leave if port was deleted from MCG */
-	if (removed && osm_sm_mcgrp_leave(sa->sm, mlid, portguid))
+	if (removed && osm_sm_mcgrp_leave(sa->sm, p_mgrp, portguid))
 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B09: "
 			"osm_sm_mcgrp_leave failed\n");
 
@@ -1310,7 +1319,7 @@ static void mcmr_rcv_join_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 	/* do the actual routing (actually schedule the update) */
 	status = osm_sm_mcgrp_join(sa->sm, mlid,
 				   p_recvd_mcmember_rec->port_gid.unicast.
-				   interface_id);
+				   interface_id, &p_recvd_mcmember_rec->mgid);
 
 	if (status != IB_SUCCESS) {
 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B14: "
@@ -1555,6 +1564,8 @@ 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;
+	cl_fmap_item_t *p_fitem;
+	osm_mgrp_holder_t *p_mgrp_holder;
 	int i;
 
 	OSM_LOG_ENTER(sa->p_log);
@@ -1586,10 +1597,18 @@ static void mcmr_query_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw)
 	/* 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)
+		p_mgrp_holder = sa->p_subn->mgroup_holders[i];
+		if (!p_mgrp_holder)
+			continue;
+		p_fitem = cl_fmap_head(&p_mgrp_holder->mgrp_map);
+		while (p_fitem != cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+			p_mgrp =
+			    (osm_mgrp_t *) PARENT_STRUCT(p_fitem, osm_mgrp_t,
+							 mgid_item);
 			mcmr_by_comp_mask(sa, p_rcvd_rec, comp_mask, p_mgrp,
 					  p_req_physp, trusted_req, &rec_list);
+			p_fitem = cl_fmap_next(p_fitem);
+		}
 	}
 
 	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 9b50deb..3271289 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.
@@ -1438,6 +1438,7 @@ static osm_mgrp_t *pr_get_mgrp(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_holder_t *p_mgrp_holder;
 	osm_mgrp_t *mgrp = NULL;
 
 	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
@@ -1468,11 +1469,30 @@ static osm_mgrp_t *pr_get_mgrp(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
 				mgrp = NULL;
 				goto Exit;
 			}
-		} else
-		    if (!(mgrp = osm_get_mgrp_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);
+		} else {
+			cl_fmap_item_t *p_fitem;
+			p_mgrp_holder =
+			    osm_get_mgrp_holder_by_mlid(sa->p_subn, p_pr->dlid);
+			if (p_mgrp_holder) {
+				p_fitem =
+				    cl_fmap_get(&p_mgrp_holder->mgrp_map,
+						&p_pr->dgid);
+			}
+			if (!p_mgrp_holder
+			    || p_fitem ==
+			    cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR,
+					"ERR 1F11: "
+					"No MC group found for PathRecord "
+					"destination LID 0x%x\n", p_pr->dlid);
+			} else {
+				mgrp =
+				    (osm_mgrp_t *) PARENT_STRUCT(p_fitem,
+								 osm_mgrp_t,
+								 mgid_item);
+			}
+
+		}
 	}
 
 Exit:
diff --git a/opensm/opensm/osm_sm.c b/opensm/opensm/osm_sm.c
index daa60ff..459e2cc 100644
--- a/opensm/opensm/osm_sm.c
+++ b/opensm/opensm/osm_sm.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.
@@ -47,6 +47,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <arpa/inet.h>
 #include <iba/ib_types.h>
 #include <complib/cl_qmap.h>
 #include <complib/cl_passivelock.h>
@@ -468,12 +469,15 @@ static ib_api_status_t sm_mgrp_process(IN osm_sm_t * p_sm,
 /**********************************************************************
  **********************************************************************/
 ib_api_status_t osm_sm_mcgrp_join(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
-				  IN const ib_net64_t port_guid)
+				  IN const ib_net64_t port_guid,
+				  IN const ib_gid_t * p_mgid)
 {
-	osm_mgrp_t *p_mgrp;
+	osm_mgrp_t *p_mgrp = NULL;
 	osm_port_t *p_port;
 	ib_api_status_t status = IB_SUCCESS;
 	osm_mcm_info_t *p_mcm;
+	cl_fmap_item_t *p_fitem;
+	osm_mgrp_holder_t *p_mgrp_holder;
 
 	OSM_LOG_ENTER(p_sm->p_log);
 
@@ -498,8 +502,51 @@ ib_api_status_t osm_sm_mcgrp_join(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
 	/*
 	 * If this multicast group does not already exist, create it.
 	 */
-	p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid);
-	if (!p_mgrp || !osm_mgrp_is_guid(p_mgrp, port_guid)) {
+	p_mgrp_holder = osm_get_mgrp_holder_by_mlid(p_sm->p_subn, mlid);
+	if (p_mgrp_holder) {
+		char gid_str[INET6_ADDRSTRLEN];
+		if (osm_is_debug()) {
+			size_t gr_count =
+			    cl_fmap_count(&p_mgrp_holder->mgrp_map);
+			OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
+				"mlid 0x%X has  %d mgroups\n", cl_ntoh16(mlid),
+				gr_count);
+			if (gr_count) {
+				p_fitem =
+				    cl_fmap_head(&p_mgrp_holder->mgrp_map);
+				while (p_fitem !=
+				       cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+					p_mgrp =
+					    (osm_mgrp_t *)
+					    PARENT_STRUCT(p_fitem, osm_mgrp_t,
+							  mgid_item);
+					OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
+						"mlid  0x%X has mgrp with MGID: %s\n",
+						cl_ntoh16(mlid),
+						inet_ntop(AF_INET6,
+							  p_mgrp->mcmember_rec.
+							  mgid.raw, gid_str,
+							  sizeof gid_str));
+					p_fitem = cl_fmap_next(p_fitem);
+				}
+			}
+		}
+		p_fitem = cl_fmap_get(&p_mgrp_holder->mgrp_map, p_mgid);
+		if (p_fitem == cl_fmap_end(&p_mgrp_holder->mgrp_map)) {
+			p_mgrp = NULL;
+			OSM_LOG(p_sm->p_log, OSM_LOG_ERROR,
+				"group with MGID: %s not found on mlid 0x%X\n",
+				inet_ntop(AF_INET6,
+					  p_mgid->raw,
+					  gid_str, sizeof gid_str),
+				cl_ntoh16(mlid));
+		} else {
+			p_mgrp =
+			    (osm_mgrp_t *) PARENT_STRUCT(p_fitem, osm_mgrp_t,
+							 mgid_item);
+		}
+	}
+	if (!p_mgrp_holder || !p_mgrp || !osm_mgrp_is_guid(p_mgrp, port_guid)) {
 		/*
 		 * The group removed or the port is not a
 		 * member of the group, then fail immediately.
@@ -514,7 +561,23 @@ ib_api_status_t osm_sm_mcgrp_join(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
 		status = IB_NOT_FOUND;
 		goto Exit;
 	}
-
+	/* if there was no change from the last time
+	 * we processed the group we can skip doing anything
+	 */
+	if (p_mgrp_holder->last_change_id == p_mgrp_holder->last_tree_id) {
+		CL_PLOCK_RELEASE(p_sm->p_lock);
+		OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE,
+			"Skip processing mgrp holder with lid:0x%X last change id:%u\n",
+			cl_ntoh16(mlid), p_mgrp_holder->last_change_id);
+		goto Exit;
+	} else {
+		OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
+			"processing mgrp holder with lid:0x%X port: 0x%016"
+			PRIx64 " last change id:%u tree id:%u\n",
+			cl_ntoh16(mlid), cl_ntoh64(port_guid),
+			p_mgrp_holder->last_change_id,
+			p_mgrp_holder->last_tree_id);
+	}
 	/*
 	 * Check if the object (according to mlid) already exists on this port.
 	 * If it does - then no need to update it again, and no need to
@@ -543,9 +606,6 @@ ib_api_status_t osm_sm_mcgrp_join(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
 		goto Exit;
 	}
 
-	status = sm_mgrp_process(p_sm, p_mgrp);
-	CL_PLOCK_RELEASE(p_sm->p_lock);
-
 Exit:
 	OSM_LOG_EXIT(p_sm->p_log);
 	return status;
@@ -553,12 +613,13 @@ Exit:
 
 /**********************************************************************
  **********************************************************************/
-ib_api_status_t osm_sm_mcgrp_leave(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
+ib_api_status_t osm_sm_mcgrp_leave(IN osm_sm_t * p_sm, IN osm_mgrp_t * p_mgrp,
 				   IN const ib_net64_t port_guid)
 {
-	osm_mgrp_t *p_mgrp;
 	osm_port_t *p_port;
 	ib_api_status_t status;
+	osm_mgrp_holder_t *p_mgrp_holder;
+	ib_net16_t mlid = p_mgrp->mlid;
 
 	OSM_LOG_ENTER(p_sm->p_log);
 
@@ -584,8 +645,8 @@ ib_api_status_t osm_sm_mcgrp_leave(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
 	/*
 	 * Get the multicast group object for this group.
 	 */
-	p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid);
-	if (!p_mgrp) {
+	p_mgrp_holder = osm_get_mgrp_holder_by_mlid(p_sm->p_subn, mlid);
+	if (!p_mgrp_holder) {
 		CL_PLOCK_RELEASE(p_sm->p_lock);
 		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E08: "
 			"No multicast group for MLID 0x%X\n", cl_ntoh16(mlid));
@@ -593,11 +654,14 @@ ib_api_status_t osm_sm_mcgrp_leave(IN osm_sm_t * p_sm, IN const ib_net16_t mlid,
 		goto Exit;
 	}
 
+	osm_mgrp_holder_delete_mgrp_port(p_mgrp_holder, p_mgrp, port_guid);
 	/*
 	 * Walk the list of ports in the group, and remove the appropriate one.
 	 */
 	osm_port_remove_mgrp(p_port, mlid);
-
+	OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
+		" Calling sm_mgrp_process for mgrp with mlid = 0x%X\n",
+		cl_ntoh16(mlid));
 	status = sm_mgrp_process(p_sm, p_mgrp);
 	CL_PLOCK_RELEASE(p_sm->p_lock);
 
diff --git a/opensm/opensm/osm_subnet.c b/opensm/opensm/osm_subnet.c
index ec15f8a..e6e624d 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.
@@ -419,7 +419,7 @@ void osm_subn_destroy(IN osm_subn_t * const p_subn)
 	osm_switch_t *p_sw, *p_next_sw;
 	osm_remote_sm_t *p_rsm, *p_next_rsm;
 	osm_prtn_t *p_prtn, *p_next_prtn;
-	osm_mgrp_t *p_mgrp;
+	osm_mgrp_holder_t *p_osm_mgrp_holder;
 	osm_infr_t *p_infr, *p_next_infr;
 
 	/* it might be a good idea to de-allocate all known objects */
@@ -464,10 +464,10 @@ void osm_subn_destroy(IN osm_subn_t * const p_subn)
 
 	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_osm_mgrp_holder = p_subn->mgroup_holders[i];
+		if (p_osm_mgrp_holder){
+				osm_mgrp_holder_delete(p_subn, p_osm_mgrp_holder->mlid);
+		}
 	}
 
 	p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list);
-- 
1.5.5




More information about the general mailing list