Blame opensm/osm_multicast.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
Packit 13e616
 *
Packit 13e616
 * This software is available to you under a choice of one of two
Packit 13e616
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 13e616
 * General Public License (GPL) Version 2, available from the file
Packit 13e616
 * COPYING in the main directory of this source tree, or the
Packit 13e616
 * OpenIB.org BSD license below:
Packit 13e616
 *
Packit 13e616
 *     Redistribution and use in source and binary forms, with or
Packit 13e616
 *     without modification, are permitted provided that the following
Packit 13e616
 *     conditions are met:
Packit 13e616
 *
Packit 13e616
 *      - Redistributions of source code must retain the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer.
Packit 13e616
 *
Packit 13e616
 *      - Redistributions in binary form must reproduce the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer in the documentation and/or other materials
Packit 13e616
 *        provided with the distribution.
Packit 13e616
 *
Packit 13e616
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 13e616
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 13e616
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 13e616
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 13e616
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 13e616
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 13e616
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 13e616
 * SOFTWARE.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *    Implementation of multicast functions.
Packit 13e616
 */
Packit 13e616
Packit 13e616
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <arpa/inet.h>
Packit 13e616
#include <opensm/osm_file_ids.h>
Packit 13e616
#define FILE_ID OSM_FILE_MULTICAST_C
Packit 13e616
#include <opensm/osm_multicast.h>
Packit 13e616
#include <opensm/osm_mcm_port.h>
Packit 13e616
#include <opensm/osm_mtree.h>
Packit 13e616
#include <opensm/osm_inform.h>
Packit 13e616
#include <opensm/osm_opensm.h>
Packit 13e616
Packit 13e616
static osm_mgrp_box_t *mgrp_box_new(uint16_t mlid)
Packit 13e616
{
Packit 13e616
	osm_mgrp_box_t *mbox = malloc(sizeof(*mbox));
Packit 13e616
	if (!mbox)
Packit 13e616
		return NULL;
Packit 13e616
Packit 13e616
	memset(mbox, 0, sizeof(*mbox));
Packit 13e616
	mbox->mlid = mlid;
Packit 13e616
	cl_qlist_init(&mbox->mgrp_list);
Packit 13e616
Packit 13e616
	return mbox;
Packit 13e616
}
Packit 13e616
Packit 13e616
void mgrp_box_delete(osm_mgrp_box_t *mbox)
Packit 13e616
{
Packit 13e616
	osm_mtree_destroy(mbox->root);
Packit 13e616
	free(mbox);
Packit 13e616
}
Packit 13e616
Packit 13e616
void mgrp_delete(IN osm_mgrp_t * p_mgrp)
Packit 13e616
{
Packit 13e616
	osm_mcm_alias_guid_t *p_mcm_alias_guid, *p_next_mcm_alias_guid;
Packit 13e616
	osm_mcm_port_t *p_mcm_port, *p_next_mcm_port;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_mgrp);
Packit 13e616
Packit 13e616
	p_next_mcm_alias_guid =
Packit 13e616
	    (osm_mcm_alias_guid_t *) cl_qmap_head(&p_mgrp->mcm_alias_port_tbl);
Packit 13e616
	while (p_next_mcm_alias_guid !=
Packit 13e616
	       (osm_mcm_alias_guid_t *) cl_qmap_end(&p_mgrp->mcm_alias_port_tbl)) {
Packit 13e616
		p_mcm_alias_guid = p_next_mcm_alias_guid;
Packit 13e616
		p_next_mcm_alias_guid =
Packit 13e616
		    (osm_mcm_alias_guid_t *) cl_qmap_next(&p_mcm_alias_guid->map_item);
Packit 13e616
		osm_mcm_alias_guid_delete(&p_mcm_alias_guid);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_next_mcm_port =
Packit 13e616
	    (osm_mcm_port_t *) cl_qmap_head(&p_mgrp->mcm_port_tbl);
Packit 13e616
	while (p_next_mcm_port !=
Packit 13e616
	       (osm_mcm_port_t *) cl_qmap_end(&p_mgrp->mcm_port_tbl)) {
Packit 13e616
		p_mcm_port = p_next_mcm_port;
Packit 13e616
		p_next_mcm_port =
Packit 13e616
		    (osm_mcm_port_t *) cl_qmap_next(&p_mcm_port->map_item);
Packit 13e616
		osm_mcm_port_delete(p_mcm_port);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	free(p_mgrp);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_mgrp_box_delete(osm_mgrp_box_t *mbox)
Packit 13e616
{
Packit 13e616
	osm_mgrp_t *mgrp;
Packit 13e616
Packit 13e616
	while (cl_qlist_count(&mbox->mgrp_list)) {
Packit 13e616
		mgrp = cl_item_obj(cl_qlist_remove_head(&mbox->mgrp_list),
Packit 13e616
				   mgrp, list_item);
Packit 13e616
		mgrp_delete(mgrp);
Packit 13e616
	}
Packit 13e616
	mgrp_box_delete(mbox);
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_mgrp_t *osm_mgrp_new(IN osm_subn_t * subn, IN ib_net16_t mlid,
Packit 13e616
			 IN ib_member_rec_t * mcmr)
Packit 13e616
{
Packit 13e616
	osm_mgrp_t *p_mgrp;
Packit 13e616
	osm_mgrp_box_t *mbox;
Packit 13e616
Packit 13e616
	p_mgrp = (osm_mgrp_t *) malloc(sizeof(*p_mgrp));
Packit 13e616
	if (!p_mgrp)
Packit 13e616
		return NULL;
Packit 13e616
Packit 13e616
	memset(p_mgrp, 0, sizeof(*p_mgrp));
Packit 13e616
	cl_qmap_init(&p_mgrp->mcm_port_tbl);
Packit 13e616
	cl_qmap_init(&p_mgrp->mcm_alias_port_tbl);
Packit 13e616
	p_mgrp->mlid = mlid;
Packit 13e616
	p_mgrp->mcmember_rec = *mcmr;
Packit 13e616
Packit 13e616
	mbox = osm_get_mbox_by_mlid(subn, p_mgrp->mlid);
Packit 13e616
	if (!mbox && !(mbox = mgrp_box_new(cl_ntoh16(p_mgrp->mlid)))) {
Packit 13e616
		free(p_mgrp);
Packit 13e616
		return NULL;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	cl_qlist_insert_tail(&mbox->mgrp_list, &p_mgrp->list_item);
Packit 13e616
	subn->mboxes[mbox->mlid - IB_LID_MCAST_START_HO] = mbox;
Packit 13e616
Packit 13e616
	cl_fmap_insert(&subn->mgrp_mgid_tbl, &p_mgrp->mcmember_rec.mgid,
Packit 13e616
		       &p_mgrp->map_item);
Packit 13e616
Packit 13e616
	subn->p_osm->sa.dirty = TRUE;
Packit 13e616
	return p_mgrp;
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mgrp)
Packit 13e616
{
Packit 13e616
	osm_mgrp_box_t *mbox;
Packit 13e616
	osm_mcm_alias_guid_t *mcm_alias_guid;
Packit 13e616
	osm_mcm_port_t *mcm_port;
Packit 13e616
Packit 13e616
	if (mgrp->full_members)
Packit 13e616
		return;
Packit 13e616
Packit 13e616
	while (cl_qmap_count(&mgrp->mcm_alias_port_tbl)) {
Packit 13e616
		mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_head(&mgrp->mcm_alias_port_tbl);
Packit 13e616
		cl_qmap_remove_item(&mgrp->mcm_alias_port_tbl, &mcm_alias_guid->map_item);
Packit 13e616
		osm_mcm_alias_guid_delete(&mcm_alias_guid);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	while (cl_qmap_count(&mgrp->mcm_port_tbl)) {
Packit 13e616
		mcm_port = (osm_mcm_port_t *) cl_qmap_head(&mgrp->mcm_port_tbl);
Packit 13e616
		cl_qmap_remove_item(&mgrp->mcm_port_tbl, &mcm_port->map_item);
Packit 13e616
		cl_qlist_remove_item(&mcm_port->port->mcm_list,
Packit 13e616
				     &mcm_port->list_item);
Packit 13e616
		osm_mcm_port_delete(mcm_port);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (mgrp->well_known)
Packit 13e616
		return;
Packit 13e616
Packit 13e616
	cl_fmap_remove_item(&subn->mgrp_mgid_tbl, &mgrp->map_item);
Packit 13e616
Packit 13e616
	mbox = osm_get_mbox_by_mlid(subn, mgrp->mlid);
Packit 13e616
	cl_qlist_remove_item(&mbox->mgrp_list, &mgrp->list_item);
Packit 13e616
	if (cl_is_qlist_empty(&mbox->mgrp_list)) {
Packit 13e616
		subn->mboxes[cl_ntoh16(mgrp->mlid) - IB_LID_MCAST_START_HO] = NULL;
Packit 13e616
		mgrp_box_delete(mbox);
Packit 13e616
	}
Packit 13e616
	free(mgrp);
Packit 13e616
Packit 13e616
	subn->p_osm->sa.dirty = TRUE;
Packit 13e616
}
Packit 13e616
Packit 13e616
static void mgrp_send_notice(osm_subn_t * subn, osm_log_t * log,
Packit 13e616
			     osm_mgrp_t * mgrp, unsigned num)
Packit 13e616
{
Packit 13e616
	ib_mad_notice_attr_t notice;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT;	/* is generic subn mgt type */
Packit 13e616
	ib_notice_set_prod_type_ho(&notice, 4);	/* A Class Manager generator */
Packit 13e616
	notice.g_or_v.generic.trap_num = CL_HTON16(num);
Packit 13e616
	/* The sm_base_lid is saved in network order already. */
Packit 13e616
	notice.issuer_lid = subn->sm_base_lid;
Packit 13e616
	/* following o14-12.1.11 and table 120 p726 */
Packit 13e616
	/* we need to provide the MGID */
Packit 13e616
	memcpy(&notice.data_details.ntc_64_67.gid,
Packit 13e616
	       &mgrp->mcmember_rec.mgid, sizeof(ib_gid_t));
Packit 13e616
Packit 13e616
	/* According to page 653 - the issuer gid in this case of trap
Packit 13e616
	   is the SM gid, since the SM is the initiator of this trap. */
Packit 13e616
	notice.issuer_gid.unicast.prefix = subn->opt.subnet_prefix;
Packit 13e616
	notice.issuer_gid.unicast.interface_id = subn->sm_port_guid;
Packit 13e616
Packit 13e616
	if ((status = osm_report_notice(log, subn, &notice)))
Packit 13e616
		OSM_LOG(log, OSM_LOG_ERROR, "ERR 7601: "
Packit 13e616
			"Error sending trap reports (%s)\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
}
Packit 13e616
Packit 13e616
static boolean_t is_qmap_empty_for_port(IN const cl_qmap_t * const p_map,
Packit 13e616
					IN const osm_port_t *port)
Packit 13e616
{
Packit 13e616
	size_t count = 0;
Packit 13e616
	cl_map_item_t *item;
Packit 13e616
	osm_mcm_alias_guid_t *mcm_alias_guid;
Packit 13e616
Packit 13e616
	for (item = cl_qmap_head(p_map); item != cl_qmap_end(p_map);
Packit 13e616
	     item = cl_qmap_next(item)) {
Packit 13e616
		mcm_alias_guid = (osm_mcm_alias_guid_t *) item;
Packit 13e616
		if (mcm_alias_guid->p_base_mcm_port->port == port) {
Packit 13e616
			count++;
Packit 13e616
			break;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	return (count == 0);
Packit 13e616
}
Packit 13e616
Packit 13e616
static boolean_t is_qmap_empty_for_mcm_port(IN const cl_qmap_t * const p_map,
Packit 13e616
					    IN const osm_mcm_port_t *mcm_port)
Packit 13e616
{
Packit 13e616
	size_t count = 0;
Packit 13e616
	cl_map_item_t *item;
Packit 13e616
	osm_mcm_alias_guid_t *mcm_alias_guid;
Packit 13e616
Packit 13e616
	for (item = cl_qmap_head(p_map); item != cl_qmap_end(p_map);
Packit 13e616
	     item = cl_qmap_next(item)) {
Packit 13e616
		mcm_alias_guid = (osm_mcm_alias_guid_t *) item;
Packit 13e616
		if (mcm_alias_guid->p_base_mcm_port == mcm_port) {
Packit 13e616
			count++;
Packit 13e616
			break;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	return (count == 0);
Packit 13e616
}
Packit 13e616
static osm_mcm_alias_guid_t *insert_alias_guid(IN osm_mgrp_t * mgrp,
Packit 13e616
					       IN osm_mcm_alias_guid_t * p_mcm_alias_guid)
Packit 13e616
{
Packit 13e616
	osm_mcm_alias_guid_t *p_mcm_alias_guid_check;
Packit 13e616
Packit 13e616
	/* insert into mcm alias guid table */
Packit 13e616
	p_mcm_alias_guid_check =
Packit 13e616
		(osm_mcm_alias_guid_t *) cl_qmap_insert(&mgrp->mcm_alias_port_tbl,
Packit 13e616
							p_mcm_alias_guid->alias_guid,
Packit 13e616
							&p_mcm_alias_guid->map_item);
Packit 13e616
	if (p_mcm_alias_guid_check != (osm_mcm_alias_guid_t *) &p_mcm_alias_guid->map_item) {
Packit 13e616
		/* alias GUID is a duplicate */
Packit 13e616
		osm_mcm_alias_guid_delete(&p_mcm_alias_guid);
Packit 13e616
		return p_mcm_alias_guid_check;
Packit 13e616
	}
Packit 13e616
	return NULL;
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_mcm_port_t *osm_mgrp_add_port(IN osm_subn_t * subn, osm_log_t * log,
Packit 13e616
				  IN osm_mgrp_t * mgrp, osm_port_t *port,
Packit 13e616
				  IN ib_member_rec_t *mcmr, IN boolean_t proxy)
Packit 13e616
{
Packit 13e616
	osm_mcm_port_t *mcm_port;
Packit 13e616
	osm_mcm_alias_guid_t *p_mcm_alias_guid, *p_mcm_alias_guid_check;
Packit 13e616
	cl_map_item_t *prev_item;
Packit 13e616
	uint8_t prev_join_state = 0, join_state = mcmr->scope_state;
Packit 13e616
	uint8_t prev_scope, full_join_state;
Packit 13e616
Packit 13e616
	if (OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_VERBOSE)) {
Packit 13e616
		char gid_str[INET6_ADDRSTRLEN];
Packit 13e616
		OSM_LOG(log, OSM_LOG_VERBOSE, "GUID 0x%016" PRIx64
Packit 13e616
			" Port 0x%016" PRIx64 " joining "
Packit 13e616
			"MC group %s (mlid 0x%x)\n",
Packit 13e616
			cl_ntoh64(mcmr->port_gid.unicast.interface_id),
Packit 13e616
			cl_ntoh64(port->guid),
Packit 13e616
			inet_ntop(AF_INET6, mgrp->mcmember_rec.mgid.raw,
Packit 13e616
				  gid_str, sizeof(gid_str)),
Packit 13e616
			cl_ntoh16(mgrp->mlid));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	mcm_port = osm_mcm_port_new(port, mgrp);
Packit 13e616
	if (!mcm_port)
Packit 13e616
		return NULL;
Packit 13e616
Packit 13e616
	p_mcm_alias_guid = osm_mcm_alias_guid_new(mcm_port, mcmr, proxy);
Packit 13e616
	if (!p_mcm_alias_guid) {
Packit 13e616
		osm_mcm_port_delete(mcm_port);
Packit 13e616
		return NULL;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   prev_item = cl_qmap_insert(...)
Packit 13e616
	   Pointer to the item in the map with the specified key.  If insertion
Packit 13e616
	   was successful, this is the pointer to the item.  If an item with the
Packit 13e616
	   specified key already exists in the map, the pointer to that item is
Packit 13e616
	   returned.
Packit 13e616
	 */
Packit 13e616
	prev_item = cl_qmap_insert(&mgrp->mcm_port_tbl, port->guid,
Packit 13e616
				   &mcm_port->map_item);
Packit 13e616
Packit 13e616
	if (prev_item != &mcm_port->map_item) {	/* mcm port already exists */
Packit 13e616
		osm_mcm_port_delete(mcm_port);
Packit 13e616
		mcm_port = (osm_mcm_port_t *) prev_item;
Packit 13e616
Packit 13e616
		p_mcm_alias_guid->p_base_mcm_port = (osm_mcm_port_t *) prev_item;
Packit 13e616
		p_mcm_alias_guid_check = insert_alias_guid(mgrp, p_mcm_alias_guid);
Packit 13e616
		if (p_mcm_alias_guid_check) {	/* alias GUID already exists */
Packit 13e616
			p_mcm_alias_guid = p_mcm_alias_guid_check;
Packit 13e616
			ib_member_get_scope_state(p_mcm_alias_guid->scope_state,
Packit 13e616
						  &prev_scope, &prev_join_state);
Packit 13e616
			p_mcm_alias_guid->scope_state =
Packit 13e616
			    ib_member_set_scope_state(prev_scope,
Packit 13e616
						      prev_join_state | join_state);
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		insert_alias_guid(mgrp, p_mcm_alias_guid);
Packit 13e616
		cl_qlist_insert_tail(&port->mcm_list, &mcm_port->list_item);
Packit 13e616
		osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* o15.0.1.11: copy the join state */
Packit 13e616
	mcmr->scope_state = p_mcm_alias_guid->scope_state;
Packit 13e616
Packit 13e616
	full_join_state = IB_JOIN_STATE_FULL | IB_JOIN_STATE_SEND_ONLY_FULL;
Packit 13e616
	if ((join_state & full_join_state) && !(prev_join_state & full_join_state) &&
Packit 13e616
	    ++mgrp->full_members == 1)
Packit 13e616
		mgrp_send_notice(subn, log, mgrp, SM_MGID_CREATED_TRAP); /* 66 */
Packit 13e616
Packit 13e616
	subn->p_osm->sa.dirty = TRUE;
Packit 13e616
	return mcm_port;
Packit 13e616
}
Packit 13e616
Packit 13e616
boolean_t osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
Packit 13e616
			  osm_mcm_alias_guid_t * mcm_alias_guid,
Packit 13e616
			  ib_member_rec_t *mcmr)
Packit 13e616
{
Packit 13e616
	uint8_t join_state = mcmr->scope_state & 0xf;
Packit 13e616
	uint8_t port_join_state, new_join_state, full_join_state;
Packit 13e616
	boolean_t mgrp_deleted = FALSE;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * according to the same o15-0.1.14 we get the stored
Packit 13e616
	 * JoinState and the request JoinState and they must be
Packit 13e616
	 * opposite to leave - otherwise just update it
Packit 13e616
	 */
Packit 13e616
	port_join_state = mcm_alias_guid->scope_state & 0x0F;
Packit 13e616
	new_join_state = port_join_state & ~join_state;
Packit 13e616
Packit 13e616
	if (OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_VERBOSE)) {
Packit 13e616
		char gid_str[INET6_ADDRSTRLEN];
Packit 13e616
		OSM_LOG(log, OSM_LOG_VERBOSE,
Packit 13e616
			"GUID 0x%" PRIx64 " Port 0x%" PRIx64
Packit 13e616
			" leaving MC group %s (mlid 0x%x)\n",
Packit 13e616
			cl_ntoh64(mcm_alias_guid->alias_guid),
Packit 13e616
			cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid),
Packit 13e616
			inet_ntop(AF_INET6, mgrp->mcmember_rec.mgid.raw,
Packit 13e616
				  gid_str, sizeof(gid_str)),
Packit 13e616
			cl_ntoh16(mgrp->mlid));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (new_join_state & IB_JOIN_STATE_FULL ||
Packit 13e616
	    (new_join_state &&
Packit 13e616
	     (mgrp->full_members > (port_join_state & IB_JOIN_STATE_FULL) ? 1 : 0))) {
Packit 13e616
		mcm_alias_guid->scope_state =
Packit 13e616
		    new_join_state | (mcm_alias_guid->scope_state & 0xf0);
Packit 13e616
		OSM_LOG(log, OSM_LOG_DEBUG,
Packit 13e616
			"updating GUID 0x%" PRIx64 " port 0x%" PRIx64
Packit 13e616
			" JoinState 0x%x -> 0x%x\n",
Packit 13e616
			cl_ntoh64(mcm_alias_guid->alias_guid),
Packit 13e616
			cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid),
Packit 13e616
			port_join_state, new_join_state);
Packit 13e616
		mcmr->scope_state = mcm_alias_guid->scope_state;
Packit 13e616
	} else {
Packit 13e616
		mcmr->scope_state = mcm_alias_guid->scope_state & 0xf0;
Packit 13e616
		OSM_LOG(log, OSM_LOG_DEBUG, "removing alias GUID 0x%" PRIx64 "\n",
Packit 13e616
			cl_ntoh64(mcm_alias_guid->alias_guid));
Packit 13e616
		cl_qmap_remove_item(&mgrp->mcm_alias_port_tbl,
Packit 13e616
				    &mcm_alias_guid->map_item);
Packit 13e616
		if (is_qmap_empty_for_port(&mgrp->mcm_alias_port_tbl,
Packit 13e616
					   mcm_alias_guid->p_base_mcm_port->port)) { /* last alias in mcast group for this port */
Packit 13e616
			OSM_LOG(log, OSM_LOG_DEBUG, "removing port 0x%" PRIx64 "\n",
Packit 13e616
				cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid));
Packit 13e616
			cl_qmap_remove_item(&mgrp->mcm_port_tbl,
Packit 13e616
					    &mcm_alias_guid->p_base_mcm_port->map_item);
Packit 13e616
			cl_qlist_remove_item(&mcm_alias_guid->p_base_mcm_port->port->mcm_list,
Packit 13e616
					     &mcm_alias_guid->p_base_mcm_port->list_item);
Packit 13e616
			if (is_qmap_empty_for_mcm_port(&mgrp->mcm_alias_port_tbl,
Packit 13e616
						       mcm_alias_guid->p_base_mcm_port)) /* last alias in mcast group for this mcm port */
Packit 13e616
				osm_mcm_port_delete(mcm_alias_guid->p_base_mcm_port);
Packit 13e616
			osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid);
Packit 13e616
		}
Packit 13e616
		osm_mcm_alias_guid_delete(&mcm_alias_guid);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	full_join_state = IB_JOIN_STATE_FULL | IB_JOIN_STATE_SEND_ONLY_FULL;
Packit 13e616
Packit 13e616
	/* no more full members so the group will be deleted after re-route
Packit 13e616
	   but only if it is not a well known group */
Packit 13e616
	if ((port_join_state & full_join_state) && !(new_join_state & full_join_state) &&
Packit 13e616
	    --mgrp->full_members == 0) {
Packit 13e616
		mgrp_send_notice(subn, log, mgrp, SM_MGID_DESTROYED_TRAP); /* 67 */
Packit 13e616
		osm_mgrp_cleanup(subn, mgrp);
Packit 13e616
		mgrp_deleted = TRUE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	subn->p_osm->sa.dirty = TRUE;
Packit 13e616
Packit 13e616
	return (mgrp_deleted);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_mgrp_delete_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp,
Packit 13e616
			  osm_port_t * port)
Packit 13e616
{
Packit 13e616
	osm_mcm_alias_guid_t *mcm_alias_guid, *next_mcm_alias_guid;
Packit 13e616
	ib_member_rec_t mcmrec;
Packit 13e616
	boolean_t mgrp_deleted = FALSE;
Packit 13e616
Packit 13e616
	next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_head(&mgrp->mcm_alias_port_tbl);
Packit 13e616
	while (!mgrp_deleted &&
Packit 13e616
	       next_mcm_alias_guid != (osm_mcm_alias_guid_t *) cl_qmap_end(&mgrp->mcm_alias_port_tbl)) {
Packit 13e616
		mcm_alias_guid = next_mcm_alias_guid;
Packit 13e616
		next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_next(&next_mcm_alias_guid->map_item);
Packit 13e616
		if (mcm_alias_guid->p_base_mcm_port->port == port) {
Packit 13e616
			mcmrec.scope_state = 0xf;
Packit 13e616
			mgrp_deleted = osm_mgrp_remove_port(subn, log, mgrp, mcm_alias_guid,
Packit 13e616
					     &mcmrec);
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_mcm_port_t *osm_mgrp_get_mcm_port(IN const osm_mgrp_t * p_mgrp,
Packit 13e616
				      IN ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	cl_map_item_t *item = cl_qmap_get(&p_mgrp->mcm_port_tbl, port_guid);
Packit 13e616
	if (item != cl_qmap_end(&p_mgrp->mcm_port_tbl))
Packit 13e616
		return (osm_mcm_port_t *) item;
Packit 13e616
	return NULL;
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_mcm_alias_guid_t *osm_mgrp_get_mcm_alias_guid(IN const osm_mgrp_t * p_mgrp,
Packit 13e616
						  IN ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	cl_map_item_t *item = cl_qmap_get(&p_mgrp->mcm_alias_port_tbl,
Packit 13e616
					  port_guid);
Packit 13e616
	if (item != cl_qmap_end(&p_mgrp->mcm_alias_port_tbl))
Packit 13e616
		return (osm_mcm_alias_guid_t *) item;
Packit 13e616
	return NULL;
Packit 13e616
}