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

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

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

_______________________________________________
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