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 <[email protected]>

---
 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

_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to