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