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

Slava Strebkov slavas at Voltaire.COM
Sun Jun 28 04:02:12 PDT 2009


Please ignore this message - wrongly sent.
Only review numbered patches 1-4 in this thread.

Slava

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




More information about the general mailing list