|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
|
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) 2009 HNR Consulting. 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 osm_state_mgr_t.
|
|
Packit |
13e616 |
* This file implements the State Manager object.
|
|
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 <unistd.h>
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <complib/cl_passivelock.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <complib/cl_qmap.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_STATE_MGR_C
|
|
Packit |
13e616 |
#include <opensm/osm_sm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_madw.h>
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_log.h>
|
|
Packit |
13e616 |
#include <opensm/osm_subnet.h>
|
|
Packit |
13e616 |
#include <opensm/osm_helper.h>
|
|
Packit |
13e616 |
#include <opensm/osm_msgdef.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_port.h>
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_api.h>
|
|
Packit |
13e616 |
#include <opensm/osm_inform.h>
|
|
Packit |
13e616 |
#include <opensm/osm_opensm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_congestion_control.h>
|
|
Packit |
13e616 |
#include <opensm/osm_db.h>
|
|
Packit |
13e616 |
#include <opensm/osm_service.h>
|
|
Packit |
13e616 |
#include <opensm/osm_guid.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
extern void osm_drop_mgr_process(IN osm_sm_t * sm);
|
|
Packit |
13e616 |
extern int osm_qos_setup(IN osm_opensm_t * p_osm);
|
|
Packit |
13e616 |
extern int osm_pkey_mgr_process(IN osm_opensm_t * p_osm);
|
|
Packit |
13e616 |
extern int osm_mcast_mgr_process(IN osm_sm_t * sm, boolean_t config_all);
|
|
Packit |
13e616 |
extern int osm_link_mgr_process(IN osm_sm_t * sm, IN uint8_t state);
|
|
Packit |
13e616 |
extern void osm_guid_mgr_process(IN osm_sm_t * sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_up_msg(IN const osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* This message should be written only once - when the
|
|
Packit |
13e616 |
* SM moves to Master state and the subnet is up for
|
|
Packit |
13e616 |
* the first time.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
osm_log_v2(sm->p_log, sm->p_subn->first_time_master_sweep ?
|
|
Packit |
13e616 |
OSM_LOG_SYS : OSM_LOG_INFO, FILE_ID, "SUBNET UP\n");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
sm->p_subn->opt.sweep_interval ?
|
|
Packit |
13e616 |
"SUBNET UP" : "SUBNET UP (sweep disabled)");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_reset_node_count(IN cl_map_item_t * p_map_item,
|
|
Packit |
13e616 |
IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_node_t *p_node = (osm_node_t *) p_map_item;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node->discovery_count = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_reset_port_count(IN cl_map_item_t * p_map_item,
|
|
Packit |
13e616 |
IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_port_t *p_port = (osm_port_t *) p_map_item;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port->discovery_count = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_reset_switch_count(IN cl_map_item_t * p_map_item,
|
|
Packit |
13e616 |
IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_sw->max_lid_ho != 0)
|
|
Packit |
13e616 |
p_sw->need_update = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_get_sw_info(IN cl_map_item_t * p_object, IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
osm_dr_path_t *p_dr_path;
|
|
Packit |
13e616 |
osm_madw_context_t mad_context;
|
|
Packit |
13e616 |
osm_switch_t *const p_sw = (osm_switch_t *) p_object;
|
|
Packit |
13e616 |
osm_sm_t *sm = context;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = p_sw->p_node;
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit |
13e616 |
p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(&mad_context, 0, sizeof(mad_context));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
mad_context.si_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
mad_context.si_context.set_method = FALSE;
|
|
Packit |
13e616 |
mad_context.si_context.light_sweep = TRUE;
|
|
Packit |
13e616 |
mad_context.si_context.lft_top_change = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_SWITCH_INFO, 0,
|
|
Packit |
13e616 |
FALSE, ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit |
13e616 |
0, OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3304: "
|
|
Packit |
13e616 |
"Request for SwitchInfo from 0x%" PRIx64 " failed (%s)\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)),
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Initiate a remote port info request for the given physical port
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void state_mgr_get_remote_port_info(IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_dr_path_t *p_dr_path;
|
|
Packit |
13e616 |
osm_dr_path_t rem_node_dr_path;
|
|
Packit |
13e616 |
osm_madw_context_t mad_context;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* generate a dr path leaving on the physp to the remote node */
|
|
Packit |
13e616 |
p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
memcpy(&rem_node_dr_path, p_dr_path, sizeof(osm_dr_path_t));
|
|
Packit |
13e616 |
if (osm_dr_path_extend(&rem_node_dr_path, osm_physp_get_port_num(p_physp))) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332D: "
|
|
Packit |
13e616 |
"DR path with hop count %d couldn't be extended "
|
|
Packit |
13e616 |
"so skipping PortInfo query\n",
|
|
Packit |
13e616 |
p_dr_path->hop_count);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(&mad_context, 0, sizeof(mad_context));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
mad_context.pi_context.node_guid =
|
|
Packit |
13e616 |
osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp));
|
|
Packit |
13e616 |
mad_context.pi_context.port_guid = p_physp->port_guid;
|
|
Packit |
13e616 |
mad_context.pi_context.set_method = FALSE;
|
|
Packit |
13e616 |
mad_context.pi_context.light_sweep = TRUE;
|
|
Packit |
13e616 |
mad_context.pi_context.active_transition = FALSE;
|
|
Packit |
13e616 |
mad_context.pi_context.client_rereg = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* note that with some negative logic - if the query failed it means
|
|
Packit |
13e616 |
* that there is no point in going to heavy sweep */
|
|
Packit |
13e616 |
status = osm_req_get(sm, &rem_node_dr_path, IB_MAD_ATTR_PORT_INFO, 0,
|
|
Packit |
13e616 |
TRUE, 0, 0, CL_DISP_MSGID_NONE, &mad_context);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332E: "
|
|
Packit |
13e616 |
"Request for remote PortInfo from 0x%" PRIx64 " failed (%s)\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_physp->port_guid), ib_get_err_str(status));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Initiates a thorough sweep of the subnet.
|
|
Packit |
13e616 |
Used when there is suspicion that something on the subnet has changed.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_sweep_hop_0(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
osm_dr_path_t dr_path;
|
|
Packit |
13e616 |
osm_bind_handle_t h_bind;
|
|
Packit |
13e616 |
uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(path_array, 0, sizeof(path_array));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* First, get the bind handle.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
|
|
Packit |
13e616 |
if (h_bind != OSM_BIND_INVALID_HANDLE) {
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"INITIATING HEAVY SWEEP");
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Start the sweep by clearing the port counts, then
|
|
Packit |
13e616 |
* get our own NodeInfo at 0 hops.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->node_guid_tbl,
|
|
Packit |
13e616 |
state_mgr_reset_node_count, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->port_guid_tbl,
|
|
Packit |
13e616 |
state_mgr_reset_port_count, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl,
|
|
Packit |
13e616 |
state_mgr_reset_switch_count, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Set the in_sweep_hop_0 flag in subn to be TRUE.
|
|
Packit |
13e616 |
* This will indicate the sweeping not to continue beyond the
|
|
Packit |
13e616 |
* the current node.
|
|
Packit |
13e616 |
* This is relevant for the case of SM on switch, since in the
|
|
Packit |
13e616 |
* switch info we need to signal somehow not to continue
|
|
Packit |
13e616 |
* the sweeping. */
|
|
Packit |
13e616 |
sm->p_subn->in_sweep_hop_0 = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_dr_path_init(&dr_path, 0, path_array);
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_NODE_INFO, 0,
|
|
Packit |
13e616 |
TRUE, 0, 0, CL_DISP_MSGID_NONE, NULL);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3305: "
|
|
Packit |
13e616 |
"Request for NodeInfo failed (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"No bound ports. Deferring sweep...\n");
|
|
Packit |
13e616 |
status = IB_INVALID_STATE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Clear out all existing port lid assignments
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_clean_known_lids(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
cl_ptr_vector_t *p_vec = &(sm->p_subn->port_lid_tbl);
|
|
Packit |
13e616 |
uint32_t i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we need a lock here! */
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < cl_ptr_vector_get_size(p_vec); i++)
|
|
Packit |
13e616 |
cl_ptr_vector_set(p_vec, i, NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Clear SA cache
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_sa_clean(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
cl_qmap_t *p_port_guid_tbl;
|
|
Packit |
13e616 |
osm_assigned_guids_t *p_assigned_guids, *p_next_assigned_guids;
|
|
Packit |
13e616 |
osm_alias_guid_t *p_alias_guid, *p_next_alias_guid;
|
|
Packit |
13e616 |
osm_mcm_port_t *mcm_port;
|
|
Packit |
13e616 |
osm_subn_t * p_subn;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_infr_t *p_infr;
|
|
Packit |
13e616 |
osm_svcr_t *p_svcr;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_subn = sm->p_subn;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we need a lock here! */
|
|
Packit |
13e616 |
CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_subn->opt.drop_event_subscriptions) {
|
|
Packit |
13e616 |
/* Clean InformInfo records */
|
|
Packit |
13e616 |
p_infr = (osm_infr_t *) cl_qlist_remove_head(&p_subn->sa_infr_list);
|
|
Packit |
13e616 |
while (p_infr !=
|
|
Packit |
13e616 |
(osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) {
|
|
Packit |
13e616 |
osm_infr_delete(p_infr);
|
|
Packit |
13e616 |
p_infr = (osm_infr_t *) cl_qlist_remove_head(&p_subn->sa_infr_list);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* For now, treat Service Records in same category as InformInfos */
|
|
Packit |
13e616 |
/* Clean Service records */
|
|
Packit |
13e616 |
p_svcr = (osm_svcr_t *) cl_qlist_remove_head(&p_subn->sa_sr_list);
|
|
Packit |
13e616 |
while (p_svcr !=
|
|
Packit |
13e616 |
(osm_svcr_t *) cl_qlist_end(&p_subn->sa_sr_list)) {
|
|
Packit |
13e616 |
osm_svcr_delete(p_svcr);
|
|
Packit |
13e616 |
p_svcr = (osm_svcr_t *) cl_qlist_remove_head(&p_subn->sa_sr_list);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Clean Multicast member list on each port */
|
|
Packit |
13e616 |
p_port_guid_tbl = &p_subn->port_guid_tbl;
|
|
Packit |
13e616 |
for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
|
|
Packit |
13e616 |
p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl);
|
|
Packit |
13e616 |
p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
|
|
Packit |
13e616 |
while (!cl_is_qlist_empty(&p_port->mcm_list)) {
|
|
Packit |
13e616 |
mcm_port = cl_item_obj(cl_qlist_head(&p_port->mcm_list),
|
|
Packit |
13e616 |
mcm_port, list_item);
|
|
Packit |
13e616 |
osm_mgrp_delete_port(p_subn, sm->p_log, mcm_port->mgrp,
|
|
Packit |
13e616 |
p_port);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
/* Hack - clean alias guid table from physp */
|
|
Packit |
13e616 |
free(p_port->p_physp->p_guids);
|
|
Packit |
13e616 |
p_port->p_physp->p_guids = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Clean Alias Guid work objects */
|
|
Packit |
13e616 |
while (cl_qlist_count(&p_subn->alias_guid_list))
|
|
Packit |
13e616 |
osm_guid_work_obj_delete((osm_guidinfo_work_obj_t *)
|
|
Packit |
13e616 |
cl_qlist_remove_head(&p_subn->alias_guid_list));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Clean Assigned GUIDs table */
|
|
Packit |
13e616 |
p_next_assigned_guids = (osm_assigned_guids_t *)
|
|
Packit |
13e616 |
cl_qmap_head(&p_subn->assigned_guids_tbl);
|
|
Packit |
13e616 |
while (p_next_assigned_guids !=
|
|
Packit |
13e616 |
(osm_assigned_guids_t *) cl_qmap_end(&p_subn->assigned_guids_tbl)) {
|
|
Packit |
13e616 |
p_assigned_guids = p_next_assigned_guids;
|
|
Packit |
13e616 |
p_next_assigned_guids = (osm_assigned_guids_t *)
|
|
Packit |
13e616 |
cl_qmap_next(&p_assigned_guids->map_item);
|
|
Packit |
13e616 |
cl_qmap_remove_item(&p_subn->assigned_guids_tbl,
|
|
Packit |
13e616 |
&p_assigned_guids->map_item);
|
|
Packit |
13e616 |
osm_assigned_guids_delete(&p_assigned_guids);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Clean Alias GUIDs table */
|
|
Packit |
13e616 |
p_next_alias_guid = (osm_alias_guid_t *)
|
|
Packit |
13e616 |
cl_qmap_head(&p_subn->alias_port_guid_tbl);
|
|
Packit |
13e616 |
while (p_next_alias_guid !=
|
|
Packit |
13e616 |
(osm_alias_guid_t *) cl_qmap_end(&p_subn->alias_port_guid_tbl)) {
|
|
Packit |
13e616 |
p_alias_guid = p_next_alias_guid;
|
|
Packit |
13e616 |
p_next_alias_guid = (osm_alias_guid_t *)
|
|
Packit |
13e616 |
cl_qmap_next(&p_alias_guid->map_item);
|
|
Packit |
13e616 |
if (osm_alias_guid_get_alias_guid(p_alias_guid) !=
|
|
Packit |
13e616 |
osm_alias_guid_get_base_guid(p_alias_guid)) {
|
|
Packit |
13e616 |
/* Clean if it's not base port GUID */
|
|
Packit |
13e616 |
cl_qmap_remove_item(&p_subn->alias_port_guid_tbl,
|
|
Packit |
13e616 |
&p_alias_guid->map_item);
|
|
Packit |
13e616 |
osm_alias_guid_delete(&p_alias_guid);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_subn->p_osm->sa.dirty = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Notifies the transport layer that the local LID has changed,
|
|
Packit |
13e616 |
which give it a chance to update address vectors, etc..
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_notify_lid_change(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
osm_bind_handle_t h_bind;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* First, get the bind handle.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
|
|
Packit |
13e616 |
if (h_bind == OSM_BIND_INVALID_HANDLE) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3306: "
|
|
Packit |
13e616 |
"No bound ports\n");
|
|
Packit |
13e616 |
status = IB_ERROR;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Notify the transport layer that we changed the local LID.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
status = osm_vendor_local_lid_change(h_bind);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3307: "
|
|
Packit |
13e616 |
"Vendor LID update failed (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Returns true if the SM port is down.
|
|
Packit |
13e616 |
The SM's port object must exist in the port_guid table.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static boolean_t state_mgr_is_sm_port_down(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
uint8_t state;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = sm->p_subn->sm_port_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* If we don't know our own port guid yet, assume the port is down.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (port_guid == 0) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3308: "
|
|
Packit |
13e616 |
"SM port GUID unknown\n");
|
|
Packit |
13e616 |
state = IB_LINK_DOWN;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(port_guid);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
|
|
Packit |
13e616 |
if (!p_port) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3309: "
|
|
Packit |
13e616 |
"SM port with GUID:%016" PRIx64 " is unknown\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
state = IB_LINK_DOWN;
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = p_port->p_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_port->p_node->sw &&
|
|
Packit |
13e616 |
!ib_switch_info_is_enhanced_port0(&p_port->p_node->sw->switch_info))
|
|
Packit |
13e616 |
state = IB_LINK_ACTIVE; /* base SP0 */
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
state = osm_physp_get_port_state(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_port->discovery_count) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 330A: Failed to discover SM port\n");
|
|
Packit |
13e616 |
state = IB_LINK_DOWN;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return (state == IB_LINK_DOWN);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Sweeps the node 1 hop away.
|
|
Packit |
13e616 |
This sets off a "chain reaction" that causes discovery of the subnet.
|
|
Packit |
13e616 |
Used when there is suspicion that something on the subnet has changed.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_sweep_hop_1(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_dr_path_t hop_1_path;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
|
|
Packit |
13e616 |
uint8_t num_ports;
|
|
Packit |
13e616 |
osm_physp_t *p_ext_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* First, get our own port and node objects.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
port_guid = sm->p_subn->sm_port_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(port_guid);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Set the in_sweep_hop_0 flag in subn to be FALSE.
|
|
Packit |
13e616 |
* This will indicate the sweeping to continue beyond the
|
|
Packit |
13e616 |
* the current node.
|
|
Packit |
13e616 |
* This is relevant for the case of SM on switch, since in the
|
|
Packit |
13e616 |
* switch info we need to signal that the sweeping should
|
|
Packit |
13e616 |
* continue through the switch. */
|
|
Packit |
13e616 |
sm->p_subn->in_sweep_hop_0 = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
|
|
Packit |
13e616 |
if (!p_port) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: "
|
|
Packit |
13e616 |
"No SM port object\n");
|
|
Packit |
13e616 |
status = IB_ERROR;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = p_port->p_node;
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_num = ib_node_info_get_local_port_num(&p_node->node_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Probing hop 1 on local port %u\n", port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(path_array, 0, sizeof(path_array));
|
|
Packit |
13e616 |
/* the hop_1 operations depend on the type of our node.
|
|
Packit |
13e616 |
* Currently - legal nodes that can host SM are SW and CA */
|
|
Packit |
13e616 |
switch (osm_node_get_type(p_node)) {
|
|
Packit |
13e616 |
case IB_NODE_TYPE_CA:
|
|
Packit |
13e616 |
case IB_NODE_TYPE_ROUTER:
|
|
Packit |
13e616 |
memset(&context, 0, sizeof(context));
|
|
Packit |
13e616 |
context.ni_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.ni_context.port_num = port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
path_array[1] = port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_dr_path_init(&hop_1_path, 1, path_array);
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0,
|
|
Packit |
13e616 |
TRUE, 0, 0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: "
|
|
Packit |
13e616 |
"Request for NodeInfo failed (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case IB_NODE_TYPE_SWITCH:
|
|
Packit |
13e616 |
/* Need to go over all the ports of the switch, and send a
|
|
Packit |
13e616 |
* node_info from them. This doesn't include the port 0 of the
|
|
Packit |
13e616 |
* switch, which hosts the SM.
|
|
Packit |
13e616 |
* Note: We'll send another switchInfo on port 0, since if no
|
|
Packit |
13e616 |
* ports are connected, we still want to get some response, and
|
|
Packit |
13e616 |
* have the subnet come up.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
num_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
for (port_num = 1; port_num < num_ports; port_num++) {
|
|
Packit |
13e616 |
/* go through the port only if the port is not DOWN */
|
|
Packit |
13e616 |
p_ext_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
if (p_ext_physp && ib_port_info_get_port_state
|
|
Packit |
13e616 |
(&(p_ext_physp->port_info)) > IB_LINK_DOWN) {
|
|
Packit |
13e616 |
memset(&context, 0, sizeof(context));
|
|
Packit |
13e616 |
context.ni_context.node_guid =
|
|
Packit |
13e616 |
osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.ni_context.port_num = port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
path_array[1] = port_num;
|
|
Packit |
13e616 |
osm_dr_path_init(&hop_1_path, 1, path_array);
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
status = osm_req_get(sm, &hop_1_path,
|
|
Packit |
13e616 |
IB_MAD_ATTR_NODE_INFO, 0,
|
|
Packit |
13e616 |
TRUE, 0, 0,
|
|
Packit |
13e616 |
CL_DISP_MSGID_NONE,
|
|
Packit |
13e616 |
&context);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 3312: "
|
|
Packit |
13e616 |
"Request for NodeInfo failed (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 3313: Unknown node type %d (%s)\n",
|
|
Packit |
13e616 |
osm_node_get_type(p_node), p_node->print_desc);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void query_sm_info(cl_map_item_t * item, void *cxt)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
osm_remote_sm_t *r_sm = cl_item_obj(item, r_sm, map_item);
|
|
Packit |
13e616 |
osm_sm_t *sm = cxt;
|
|
Packit |
13e616 |
ib_api_status_t ret;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port= osm_get_port_by_guid(sm->p_subn, r_sm->smi.guid);
|
|
Packit |
13e616 |
if (p_port == NULL) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3340: "
|
|
Packit |
13e616 |
"No port object on given sm object\n");
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.smi_context.port_guid = r_sm->smi.guid;
|
|
Packit |
13e616 |
context.smi_context.set_method = FALSE;
|
|
Packit |
13e616 |
context.smi_context.light_sweep = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ret = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
|
|
Packit |
13e616 |
IB_MAD_ATTR_SM_INFO, 0, FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_port->p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
if (ret != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3314: "
|
|
Packit |
13e616 |
"Failure requesting SMInfo (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(ret));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_reset_state_change_bit(IN cl_map_item_t * obj,
|
|
Packit |
13e616 |
IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_madw_context_t mad_context;
|
|
Packit |
13e616 |
osm_switch_t *p_sw = (osm_switch_t *) obj;
|
|
Packit |
13e616 |
osm_sm_t *sm = context;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
osm_dr_path_t *p_path;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
ib_switch_info_t si;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_sw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = p_sw->p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit |
13e616 |
p_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!ib_switch_info_get_state_change(&p_sw->switch_info))
|
|
Packit |
13e616 |
goto exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
si = p_sw->switch_info;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_switch_info_state_change_set(&si);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Resetting PortStateChange on switch GUID 0x%016" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
mad_context.si_context.light_sweep = FALSE;
|
|
Packit |
13e616 |
mad_context.si_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
mad_context.si_context.set_method = TRUE;
|
|
Packit |
13e616 |
mad_context.si_context.lft_top_change = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = osm_req_set(sm, p_path, (uint8_t *) &si,
|
|
Packit |
13e616 |
sizeof(si), IB_MAD_ATTR_SWITCH_INFO,
|
|
Packit |
13e616 |
0, FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &mad_context);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332A: "
|
|
Packit |
13e616 |
"Sending SwitchInfo attribute failed (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void state_mgr_update_node_desc(IN cl_map_item_t * obj, IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_madw_context_t mad_context;
|
|
Packit |
13e616 |
osm_node_t *p_node = (osm_node_t *) obj;
|
|
Packit |
13e616 |
osm_sm_t *sm = context;
|
|
Packit |
13e616 |
osm_physp_t *p_physp = NULL;
|
|
Packit |
13e616 |
unsigned i, num_ports;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Updating NodeDesc for 0x%016" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* get a physp to request from. */
|
|
Packit |
13e616 |
num_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
for (i = 0; i < num_ports; i++)
|
|
Packit |
13e616 |
if ((p_physp = osm_node_get_physp_ptr(p_node, i)))
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_physp) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: "
|
|
Packit |
13e616 |
"Failed to find any valid physical port object.\n");
|
|
Packit |
13e616 |
goto exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
|
|
Packit |
13e616 |
IB_MAD_ATTR_NODE_DESC, 0, FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &mad_context);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 331B: Failure initiating NodeDescription request "
|
|
Packit |
13e616 |
"(%s) to 0x%016" PRIx64 "\n", ib_get_err_str(status),
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_reset_switch_state_change_bit(IN osm_opensm_t *osm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(&osm->lock);
|
|
Packit |
13e616 |
cl_qmap_apply_func(&osm->subn.sw_guid_tbl, state_mgr_reset_state_change_bit,
|
|
Packit |
13e616 |
&osm->sm);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(&osm->lock);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_update_node_desc(IN osm_opensm_t *osm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(&osm->lock);
|
|
Packit |
13e616 |
cl_qmap_apply_func(&osm->subn.node_guid_tbl, state_mgr_update_node_desc,
|
|
Packit |
13e616 |
&osm->sm);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(&osm->lock);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
During a light sweep, check each node to see if the node description
|
|
Packit |
13e616 |
is valid and if not issue a ND query.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void state_mgr_get_node_desc(IN cl_map_item_t * obj, IN void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_node_t *p_node = (osm_node_t *) obj;
|
|
Packit |
13e616 |
osm_sm_t *sm = context;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_node->print_desc
|
|
Packit |
13e616 |
&& strcmp(p_node->print_desc, OSM_NODE_DESC_UNKNOWN))
|
|
Packit |
13e616 |
/* if ND is valid, do nothing */
|
|
Packit |
13e616 |
goto exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 3319: Unknown node description for node GUID "
|
|
Packit |
13e616 |
"0x%016" PRIx64 ". Reissuing ND query\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
state_mgr_update_node_desc(obj, context);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Initiates a lightweight sweep of the subnet.
|
|
Packit |
13e616 |
Used during normal sweeps after the subnet is up.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static ib_api_status_t state_mgr_light_sweep_start(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
osm_bind_handle_t h_bind;
|
|
Packit |
13e616 |
cl_qmap_t *p_sw_tbl;
|
|
Packit |
13e616 |
cl_map_item_t *p_next;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw_tbl = &sm->p_subn->sw_guid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* First, get the bind handle.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
|
|
Packit |
13e616 |
if (h_bind == OSM_BIND_INVALID_HANDLE) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"No bound ports. Deferring sweep...\n");
|
|
Packit |
13e616 |
status = IB_INVALID_STATE;
|
|
Packit |
13e616 |
goto _exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP");
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
cl_qmap_apply_func(p_sw_tbl, state_mgr_get_sw_info, sm);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_get_node_desc,
|
|
Packit |
13e616 |
sm);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* now scan the list of physical ports that were not down but have no remote port */
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl);
|
|
Packit |
13e616 |
while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) {
|
|
Packit |
13e616 |
p_node = (osm_node_t *) p_next;
|
|
Packit |
13e616 |
p_next = cl_qmap_next(p_next);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (port_num = 1; port_num < osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
port_num++) {
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
if (p_physp && (osm_physp_get_port_state(p_physp) !=
|
|
Packit |
13e616 |
IB_LINK_DOWN)
|
|
Packit |
13e616 |
&& !osm_physp_get_remote(p_physp)) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: "
|
|
Packit |
13e616 |
"Unknown remote side for node 0x%016"
|
|
Packit |
13e616 |
PRIx64
|
|
Packit |
13e616 |
" (%s) port %u. Adding to light sweep sampling list\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit |
13e616 |
(p_node)),
|
|
Packit |
13e616 |
p_node->print_desc, port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_dump_dr_path_v2(sm->p_log,
|
|
Packit |
13e616 |
osm_physp_get_dr_path_ptr
|
|
Packit |
13e616 |
(p_physp), FILE_ID, OSM_LOG_ERROR);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
state_mgr_get_remote_port_info(sm, p_physp);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
_exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
* Go over all the remote SMs (as updated in the sm_guid_tbl).
|
|
Packit |
13e616 |
* Find if there is a remote sm that is a master SM.
|
|
Packit |
13e616 |
* If there is a remote master SM - return a pointer to it,
|
|
Packit |
13e616 |
* else - return NULL.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static osm_remote_sm_t *state_mgr_exists_other_master_sm(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_qmap_t *p_sm_tbl;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_sm;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_sm_res = NULL;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sm_tbl = &sm->p_subn->sm_guid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* go over all the remote SMs */
|
|
Packit |
13e616 |
for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl);
|
|
Packit |
13e616 |
p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl);
|
|
Packit |
13e616 |
p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) {
|
|
Packit |
13e616 |
/* If the sm is in MASTER state - return a pointer to it */
|
|
Packit |
13e616 |
p_node = osm_get_node_by_guid(sm->p_subn, p_sm->smi.guid);
|
|
Packit |
13e616 |
if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Found remote master SM with guid:0x%016" PRIx64
|
|
Packit |
13e616 |
" (node %s)\n", cl_ntoh64(p_sm->smi.guid),
|
|
Packit |
13e616 |
p_node ? p_node->print_desc : "UNKNOWN");
|
|
Packit |
13e616 |
p_sm_res = p_sm;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return p_sm_res;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
* Go over all remote SMs (as updated in the sm_guid_tbl).
|
|
Packit |
13e616 |
* Find the one with the highest priority and lowest guid.
|
|
Packit |
13e616 |
* Compare this SM to the local SM. If the local SM is higher -
|
|
Packit |
13e616 |
* return NULL, if the remote SM is higher - return a pointer to it.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static osm_remote_sm_t *state_mgr_get_highest_sm(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_qmap_t *p_sm_tbl;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_sm = NULL;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_highest_sm;
|
|
Packit |
13e616 |
uint8_t highest_sm_priority;
|
|
Packit |
13e616 |
ib_net64_t highest_sm_guid;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sm_tbl = &sm->p_subn->sm_guid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Start with the local sm as the standard */
|
|
Packit |
13e616 |
p_highest_sm = NULL;
|
|
Packit |
13e616 |
highest_sm_priority = sm->p_subn->opt.sm_priority;
|
|
Packit |
13e616 |
highest_sm_guid = sm->p_subn->sm_port_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* go over all the remote SMs */
|
|
Packit |
13e616 |
for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl);
|
|
Packit |
13e616 |
p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl);
|
|
Packit |
13e616 |
p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* If the sm is in NOTACTIVE state - continue */
|
|
Packit |
13e616 |
if (ib_sminfo_get_state(&p_sm->smi) ==
|
|
Packit |
13e616 |
IB_SMINFO_STATE_NOTACTIVE)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_sm_is_greater_than(ib_sminfo_get_priority(&p_sm->smi),
|
|
Packit |
13e616 |
p_sm->smi.guid, highest_sm_priority,
|
|
Packit |
13e616 |
highest_sm_guid)) {
|
|
Packit |
13e616 |
/* the new p_sm is with higher priority - update the highest_sm */
|
|
Packit |
13e616 |
/* to this sm */
|
|
Packit |
13e616 |
p_highest_sm = p_sm;
|
|
Packit |
13e616 |
highest_sm_priority =
|
|
Packit |
13e616 |
ib_sminfo_get_priority(&p_sm->smi);
|
|
Packit |
13e616 |
highest_sm_guid = p_sm->smi.guid;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_highest_sm != NULL) {
|
|
Packit |
13e616 |
p_node = osm_get_node_by_guid(sm->p_subn, p_highest_sm->smi.guid);
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Found higher priority SM with guid: %016" PRIx64 " (node %s)\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_highest_sm->smi.guid),
|
|
Packit |
13e616 |
p_node ? p_node->print_desc : "UNKNOWN");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return p_highest_sm;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
* Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
|
|
Packit |
13e616 |
* remote_sm indicated.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void state_mgr_send_handover(IN osm_sm_t * sm, IN osm_remote_sm_t * p_sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint8_t payload[IB_SMP_DATA_SIZE];
|
|
Packit |
13e616 |
ib_sm_info_t *p_smi = (ib_sm_info_t *) payload;
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
const osm_port_t *p_port;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(&context, 0, sizeof(context));
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(sm->p_subn, p_sm->smi.guid);
|
|
Packit |
13e616 |
if (p_port == NULL) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3316: "
|
|
Packit |
13e616 |
"No port object on given remote_sm object\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* update the master_guid in the sm_state_mgr object according to */
|
|
Packit |
13e616 |
/* the guid of the port where the new Master SM should reside. */
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Handing over mastership. Updating sm_state_mgr master_guid: %016"
|
|
Packit |
13e616 |
PRIx64 " (node %s)\n", cl_ntoh64(p_port->guid),
|
|
Packit |
13e616 |
p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN");
|
|
Packit |
13e616 |
sm->master_sm_guid = p_port->guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.smi_context.port_guid = p_port->guid;
|
|
Packit |
13e616 |
context.smi_context.set_method = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(payload, 0, sizeof(payload));
|
|
Packit |
13e616 |
p_smi->guid = sm->p_subn->sm_port_guid;
|
|
Packit |
13e616 |
p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
|
|
Packit |
13e616 |
p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
|
|
Packit |
13e616 |
sm->p_subn->opt.sm_priority << 4);
|
|
Packit |
13e616 |
p_smi->sm_key = sm->p_subn->opt.sm_key;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
|
|
Packit |
13e616 |
payload, sizeof(payload), IB_MAD_ATTR_SM_INFO,
|
|
Packit |
13e616 |
IB_SMINFO_ATTR_MOD_HANDOVER, FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_port->p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3317: "
|
|
Packit |
13e616 |
"Failure requesting SMInfo (%s), remote SM at 0x%"
|
|
Packit |
13e616 |
PRIx64 " (node %s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status), cl_ntoh64(p_port->guid),
|
|
Packit |
13e616 |
p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
* Send Trap 64 on all new ports.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void state_mgr_report_new_ports(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_gid_t port_gid;
|
|
Packit |
13e616 |
ib_mad_notice_attr_t notice;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
cl_map_item_t *p_next;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
uint16_t min_lid_ho;
|
|
Packit |
13e616 |
uint16_t max_lid_ho;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl);
|
|
Packit |
13e616 |
while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) {
|
|
Packit |
13e616 |
p_port = (osm_port_t *) p_next;
|
|
Packit |
13e616 |
p_next = cl_qmap_next(p_next);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_port->is_new)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = osm_port_get_guid(p_port);
|
|
Packit |
13e616 |
/* issue a notice - trap 64 (SM_GID_IN_SERVICE_TRAP) */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* details of the notice */
|
|
Packit |
13e616 |
notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT; /* is generic subn mgt type */
|
|
Packit |
13e616 |
ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */
|
|
Packit |
13e616 |
/* endport becomes reachable */
|
|
Packit |
13e616 |
notice.g_or_v.generic.trap_num = CL_HTON16(SM_GID_IN_SERVICE_TRAP); /* 64 */
|
|
Packit |
13e616 |
/* The sm_base_lid is saved in network order already. */
|
|
Packit |
13e616 |
notice.issuer_lid = sm->p_subn->sm_base_lid;
|
|
Packit |
13e616 |
/* following C14-72.1.1 and table 119 p739 */
|
|
Packit |
13e616 |
/* we need to provide the GID */
|
|
Packit |
13e616 |
port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
|
|
Packit |
13e616 |
port_gid.unicast.interface_id = port_guid;
|
|
Packit |
13e616 |
memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid),
|
|
Packit |
13e616 |
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 =
|
|
Packit |
13e616 |
sm->p_subn->opt.subnet_prefix;
|
|
Packit |
13e616 |
notice.issuer_gid.unicast.interface_id =
|
|
Packit |
13e616 |
sm->p_subn->sm_port_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = osm_report_notice(sm->p_log, sm->p_subn, ¬ice);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: "
|
|
Packit |
13e616 |
"Error sending trap reports on GUID:0x%016"
|
|
Packit |
13e616 |
PRIx64 " (%s)\n", port_gid.unicast.interface_id,
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"Discovered new port with GUID:0x%016" PRIx64
|
|
Packit |
13e616 |
" LID range [%u,%u] of node: %s\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_gid.unicast.interface_id),
|
|
Packit |
13e616 |
min_lid_ho, max_lid_ho,
|
|
Packit |
13e616 |
p_port->p_node ? p_port->p_node->
|
|
Packit |
13e616 |
print_desc : "UNKNOWN");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port->is_new = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
* Make sure that the lid_port_tbl of the subnet has only the ports
|
|
Packit |
13e616 |
* that are recognized, and in the correct lid place. There could be
|
|
Packit |
13e616 |
* errors if we wanted to assign a certain port with lid X, but that
|
|
Packit |
13e616 |
* request didn't reach the port. In this case port_lid_tbl will have
|
|
Packit |
13e616 |
* the port under lid X, though the port isn't updated with this lid.
|
|
Packit |
13e616 |
* We will run a new heavy sweep (since there were errors in the
|
|
Packit |
13e616 |
* initialization), but here we'll clean the database from incorrect
|
|
Packit |
13e616 |
* information.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void state_mgr_check_tbl_consistency(IN osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_qmap_t *p_port_guid_tbl;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_port_t *p_next_port;
|
|
Packit |
13e616 |
cl_ptr_vector_t *p_port_lid_tbl;
|
|
Packit |
13e616 |
size_t max_lid, ref_size, curr_size, lid;
|
|
Packit |
13e616 |
osm_port_t *p_port_ref, *p_port_stored;
|
|
Packit |
13e616 |
cl_ptr_vector_t ref_port_lid_tbl;
|
|
Packit |
13e616 |
uint16_t min_lid_ho;
|
|
Packit |
13e616 |
uint16_t max_lid_ho;
|
|
Packit |
13e616 |
uint16_t lid_ho;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->lid_mgr.dirty == FALSE)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sm->lid_mgr.dirty = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_ptr_vector_construct(&ref_port_lid_tbl);
|
|
Packit |
13e616 |
cl_ptr_vector_init(&ref_port_lid_tbl,
|
|
Packit |
13e616 |
cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl),
|
|
Packit |
13e616 |
OSM_SUBNET_VECTOR_GROW_SIZE);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port_guid_tbl = &sm->p_subn->port_guid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Let's go over all the ports according to port_guid_tbl,
|
|
Packit |
13e616 |
* and add the port to a reference port_lid_tbl. */
|
|
Packit |
13e616 |
p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
|
|
Packit |
13e616 |
while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) {
|
|
Packit |
13e616 |
p_port = p_next_port;
|
|
Packit |
13e616 |
p_next_port =
|
|
Packit |
13e616 |
(osm_port_t *) cl_qmap_next(&p_next_port->map_item);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
|
|
Packit |
13e616 |
for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
|
|
Packit |
13e616 |
cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port_lid_tbl = &sm->p_subn->port_lid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl);
|
|
Packit |
13e616 |
curr_size = cl_ptr_vector_get_size(p_port_lid_tbl);
|
|
Packit |
13e616 |
/* They should be the same, but compare it anyway */
|
|
Packit |
13e616 |
max_lid = (ref_size > curr_size) ? ref_size : curr_size;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (lid = 1; lid < max_lid; lid++) {
|
|
Packit |
13e616 |
p_port_ref = NULL;
|
|
Packit |
13e616 |
p_port_stored = NULL;
|
|
Packit |
13e616 |
cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored);
|
|
Packit |
13e616 |
cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_port_stored == p_port_ref)
|
|
Packit |
13e616 |
/* This is the "good" case - both entries are the
|
|
Packit |
13e616 |
* same for this lid. Nothing to do. */
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_port_ref == NULL) {
|
|
Packit |
13e616 |
/* There is an object in the subnet database for this
|
|
Packit |
13e616 |
* lid, but no such object exists in the reference
|
|
Packit |
13e616 |
* port_list_tbl. This can occur if we wanted to assign
|
|
Packit |
13e616 |
* a certain port with some lid (different than the one
|
|
Packit |
13e616 |
* pre-assigned to it), and the port didn't get the
|
|
Packit |
13e616 |
* PortInfo Set request. Due to this, the port is
|
|
Packit |
13e616 |
* updated with its original lid in our database
|
|
Packit |
13e616 |
* rather than the new lid we wanted to give it. */
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: "
|
|
Packit |
13e616 |
"lid %zu is wrongly assigned to port 0x%016"
|
|
Packit |
13e616 |
PRIx64 " (\'%s\' port %u) in port_lid_tbl\n",
|
|
Packit |
13e616 |
lid,
|
|
Packit |
13e616 |
cl_ntoh64(osm_port_get_guid(p_port_stored)),
|
|
Packit |
13e616 |
p_port_stored->p_node->print_desc,
|
|
Packit |
13e616 |
p_port_stored->p_physp->port_num);
|
|
Packit |
13e616 |
} else if (p_port_stored == NULL)
|
|
Packit |
13e616 |
/* There is an object in the new database, but no
|
|
Packit |
13e616 |
* object in our subnet database. This is the matching
|
|
Packit |
13e616 |
* case of the prior check - the port still has its
|
|
Packit |
13e616 |
* original lid. */
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: "
|
|
Packit |
13e616 |
"port 0x%016" PRIx64 " (\'%s\' port %u)"
|
|
Packit |
13e616 |
" exists in new port_lid_tbl under lid %zu,"
|
|
Packit |
13e616 |
" but missing in subnet port_lid_tbl db\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_port_get_guid(p_port_ref)),
|
|
Packit |
13e616 |
p_port_ref->p_node->print_desc,
|
|
Packit |
13e616 |
p_port_ref->p_physp->port_num, lid);
|
|
Packit |
13e616 |
else {
|
|
Packit |
13e616 |
/* if we reached here then p_port_stored != p_port_ref.
|
|
Packit |
13e616 |
* We were trying to set a lid to p_port_stored, but
|
|
Packit |
13e616 |
* it didn't reach it, and p_port_ref also didn't get
|
|
Packit |
13e616 |
* the lid update. */
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: "
|
|
Packit |
13e616 |
"lid %zu has port 0x%016" PRIx64
|
|
Packit |
13e616 |
" (\'%s\' port %u) in new port_lid_tbl db, "
|
|
Packit |
13e616 |
"and port 0x%016" PRIx64 " (\'%s\' port %u)"
|
|
Packit |
13e616 |
" in subnet port_lid_tbl db\n", lid,
|
|
Packit |
13e616 |
cl_ntoh64(osm_port_get_guid(p_port_ref)),
|
|
Packit |
13e616 |
p_port_ref->p_node->print_desc,
|
|
Packit |
13e616 |
p_port_ref->p_physp->port_num,
|
|
Packit |
13e616 |
cl_ntoh64(osm_port_get_guid(p_port_stored)),
|
|
Packit |
13e616 |
p_port_stored->p_node->print_desc,
|
|
Packit |
13e616 |
p_port_stored->p_physp->port_num);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Clear the lid of the port in order to ignore it
|
|
Packit |
13e616 |
* in routing phase
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_port_stored) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_INFO, "Clearing Lid for "
|
|
Packit |
13e616 |
"port 0x%016" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_port_get_guid(p_port_stored)));
|
|
Packit |
13e616 |
osm_port_clear_base_lid(p_port_stored);
|
|
Packit |
13e616 |
cl_ptr_vector_set(p_port_lid_tbl, lid, NULL);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Make sure we'll do another heavy sweep. */
|
|
Packit |
13e616 |
sm->p_subn->subnet_initialization_error = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_ptr_vector_destroy(&ref_port_lid_tbl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void check_switch_lft(cl_map_item_t * item, void *log)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_switch_t *sw = (osm_switch_t *) item;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!sw->new_lft)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (memcmp(sw->lft, sw->new_lft, sw->max_lid_ho + 1))
|
|
Packit |
13e616 |
osm_log_v2(log, OSM_LOG_ERROR, FILE_ID, "ERR 331D: "
|
|
Packit |
13e616 |
"LFT of switch 0x%016" PRIx64 " (%s) is not up to date\n",
|
|
Packit |
13e616 |
cl_ntoh64(sw->p_node->node_info.node_guid),
|
|
Packit |
13e616 |
sw->p_node->print_desc);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
int wait_for_pending_transactions(osm_stats_t * stats)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
#ifdef HAVE_LIBPTHREAD
|
|
Packit |
13e616 |
pthread_mutex_lock(&stats->mutex);
|
|
Packit |
13e616 |
while (stats->qp0_mads_outstanding && !osm_exit_flag)
|
|
Packit |
13e616 |
pthread_cond_wait(&stats->cond, &stats->mutex);
|
|
Packit |
13e616 |
pthread_mutex_unlock(&stats->mutex);
|
|
Packit |
13e616 |
#else
|
|
Packit |
13e616 |
while (1) {
|
|
Packit |
13e616 |
unsigned count = stats->qp0_mads_outstanding;
|
|
Packit |
13e616 |
if (!count || osm_exit_flag)
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
cl_event_wait_on(&stats->event, EVENT_NO_TIMEOUT, TRUE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
#endif
|
|
Packit |
13e616 |
return osm_exit_flag;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void do_sweep(osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_remote_sm;
|
|
Packit |
13e616 |
unsigned config_parsed = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->force_first_time_master_sweep) {
|
|
Packit |
13e616 |
sm->p_subn->force_heavy_sweep = TRUE;
|
|
Packit |
13e616 |
sm->p_subn->coming_out_of_standby = TRUE;
|
|
Packit |
13e616 |
sm->p_subn->first_time_master_sweep = TRUE;
|
|
Packit |
13e616 |
sm->p_subn->force_first_time_master_sweep = FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* after subnet initialization error, run heavy sweep */
|
|
Packit |
13e616 |
if (sm->p_subn->subnet_initialization_error)
|
|
Packit |
13e616 |
sm->p_subn->force_heavy_sweep = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->force_heavy_sweep) {
|
|
Packit |
13e616 |
if (osm_subn_rescan_conf_files(sm->p_subn) < 0)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331A: "
|
|
Packit |
13e616 |
"osm_subn_rescan_conf_file failed\n");
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
config_parsed = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER &&
|
|
Packit |
13e616 |
sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->coming_out_of_standby) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Need to force re-write of sm_base_lid to all ports
|
|
Packit |
13e616 |
* to do that we want all the ports to be considered
|
|
Packit |
13e616 |
* foreign
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
state_mgr_clean_known_lids(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Need to clean SA cache when state changes to STANDBY
|
|
Packit |
13e616 |
* after handover.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
state_mgr_sa_clean(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Need to reconfigure LFTs, PKEYs, and QoS on all switches
|
|
Packit |
13e616 |
* when coming out of STANDBY
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
sm->p_subn->need_update = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sm->master_sm_found = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* If we already have switches, then try a light sweep.
|
|
Packit |
13e616 |
* Otherwise, this is probably our first discovery pass
|
|
Packit |
13e616 |
* or we are connected in loopback. In both cases do a
|
|
Packit |
13e616 |
* heavy sweep.
|
|
Packit |
13e616 |
* Note: If we are connected in loopback we want a heavy
|
|
Packit |
13e616 |
* sweep, since we will not be getting any traps if there is
|
|
Packit |
13e616 |
* a lost connection.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
/* if we are in DISCOVERING state - this means it is either in
|
|
Packit |
13e616 |
* initializing or wake up from STANDBY - run the heavy sweep */
|
|
Packit |
13e616 |
if (cl_qmap_count(&sm->p_subn->sw_guid_tbl)
|
|
Packit |
13e616 |
&& sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING
|
|
Packit |
13e616 |
&& sm->p_subn->opt.force_heavy_sweep == FALSE
|
|
Packit |
13e616 |
&& sm->p_subn->force_heavy_sweep == FALSE
|
|
Packit |
13e616 |
&& sm->p_subn->force_reroute == FALSE
|
|
Packit |
13e616 |
&& sm->p_subn->subnet_initialization_error == FALSE
|
|
Packit |
13e616 |
&& (state_mgr_light_sweep_start(sm) == IB_SUCCESS)) {
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
if (!sm->p_subn->force_heavy_sweep) {
|
|
Packit |
13e616 |
if (sm->p_subn->opt.sa_db_dump &&
|
|
Packit |
13e616 |
!osm_sa_db_file_dump(sm->p_subn->p_osm))
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_SA_DB_DUMPED,
|
|
Packit |
13e616 |
NULL);
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LIGHT SWEEP COMPLETE");
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Unicast cache should be invalidated when subnet re-route is
|
|
Packit |
13e616 |
* requested, and when OpenSM comes out of standby state.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (sm->p_subn->opt.use_ucast_cache &&
|
|
Packit |
13e616 |
(sm->p_subn->force_reroute || sm->p_subn->coming_out_of_standby))
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(&sm->ucast_mgr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* If we don't need to do a heavy sweep and we want to do a reroute,
|
|
Packit |
13e616 |
* just reroute only.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (cl_qmap_count(&sm->p_subn->sw_guid_tbl)
|
|
Packit |
13e616 |
&& sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING
|
|
Packit |
13e616 |
&& sm->p_subn->opt.force_heavy_sweep == FALSE
|
|
Packit |
13e616 |
&& sm->p_subn->force_heavy_sweep == FALSE
|
|
Packit |
13e616 |
&& sm->p_subn->force_reroute == TRUE
|
|
Packit |
13e616 |
&& sm->p_subn->subnet_initialization_error == FALSE) {
|
|
Packit |
13e616 |
/* Reset flag */
|
|
Packit |
13e616 |
sm->p_subn->force_reroute = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Re-program the switches fully */
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_ucast_mgr_process(&sm->ucast_mgr)) {
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"REROUTE FAILED");
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
osm_qos_setup(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Reset flag */
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_congestion_control_setup(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_congestion_control_wait_pending_transactions(sm->p_subn->p_osm))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!sm->p_subn->subnet_initialization_error) {
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"REROUTE COMPLETE");
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_UCAST_ROUTING_DONE,
|
|
Packit |
13e616 |
(void *) UCAST_ROUTING_REROUTE);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_HEAVY_SWEEP_START, NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* go to heavy sweep */
|
|
Packit |
13e616 |
repeat_discovery:
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* First of all - unset all flags */
|
|
Packit |
13e616 |
sm->p_subn->force_heavy_sweep = FALSE;
|
|
Packit |
13e616 |
sm->p_subn->force_reroute = FALSE;
|
|
Packit |
13e616 |
sm->p_subn->subnet_initialization_error = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Reset tracking values in case limiting component got removed
|
|
Packit |
13e616 |
* from fabric. */
|
|
Packit |
13e616 |
sm->p_subn->min_ca_mtu = IB_MAX_MTU;
|
|
Packit |
13e616 |
sm->p_subn->min_ca_rate = IB_RATE_MAX;
|
|
Packit |
13e616 |
sm->p_subn->min_data_vls = IB_MAX_NUM_VLS - 1;
|
|
Packit |
13e616 |
sm->p_subn->min_sw_data_vls = IB_MAX_NUM_VLS - 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* rescan configuration updates */
|
|
Packit |
13e616 |
if (!config_parsed && osm_subn_rescan_conf_files(sm->p_subn) < 0)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331A: "
|
|
Packit |
13e616 |
"osm_subn_rescan_conf_file failed\n");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
|
|
Packit |
13e616 |
sm->p_subn->need_update = 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = state_mgr_sweep_hop_0(sm);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS ||
|
|
Packit |
13e616 |
wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (state_mgr_is_sm_port_down(sm) == TRUE) {
|
|
Packit |
13e616 |
if (sm->p_subn->last_sm_port_state) {
|
|
Packit |
13e616 |
sm->p_subn->last_sm_port_state = 0;
|
|
Packit |
13e616 |
state_mgr_sa_clean(sm);
|
|
Packit |
13e616 |
osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID,
|
|
Packit |
13e616 |
"SM port is down\n");
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"SM PORT DOWN");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Run the drop manager - we want to clear all records */
|
|
Packit |
13e616 |
osm_drop_mgr_process(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Move to DISCOVERING state */
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING)
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVER);
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_STATE_CHANGE, NULL);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
if (!sm->p_subn->last_sm_port_state) {
|
|
Packit |
13e616 |
sm->p_subn->last_sm_port_state = 1;
|
|
Packit |
13e616 |
osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID,
|
|
Packit |
13e616 |
"SM port is up\n");
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"SM PORT UP");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = state_mgr_sweep_hop_1(sm);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS ||
|
|
Packit |
13e616 |
wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* discovery completed - check other sm presence */
|
|
Packit |
13e616 |
if (sm->master_sm_found) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Call the sm_state_mgr with signal
|
|
Packit |
13e616 |
* MASTER_OR_HIGHER_SM_DETECTED_DONE
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm,
|
|
Packit |
13e616 |
OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED);
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"ENTERING STANDBY STATE");
|
|
Packit |
13e616 |
/* notify master SM about us */
|
|
Packit |
13e616 |
osm_send_trap144(sm, 0);
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_STATE_CHANGE, NULL);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if new sweep requested - don't bother with the rest */
|
|
Packit |
13e616 |
if (sm->p_subn->force_heavy_sweep) {
|
|
Packit |
13e616 |
config_parsed = 0;
|
|
Packit |
13e616 |
goto repeat_discovery;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_HEAVY_SWEEP_DONE, NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "HEAVY SWEEP COMPLETE");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_drop_mgr_process(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* If we are MASTER - get the highest remote_sm, and
|
|
Packit |
13e616 |
* see if it is higher than our local sm.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) {
|
|
Packit |
13e616 |
p_remote_sm = state_mgr_get_highest_sm(sm);
|
|
Packit |
13e616 |
if (p_remote_sm != NULL) {
|
|
Packit |
13e616 |
/* report new ports (trap 64) before leaving MASTER */
|
|
Packit |
13e616 |
state_mgr_report_new_ports(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* need to handover the mastership
|
|
Packit |
13e616 |
* to the remote sm, and move to standby */
|
|
Packit |
13e616 |
state_mgr_send_handover(sm, p_remote_sm);
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm,
|
|
Packit |
13e616 |
OSM_SM_SIGNAL_HANDOVER_SENT);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/* We are the highest sm - check to see if there is
|
|
Packit |
13e616 |
* a remote SM that is in master state. */
|
|
Packit |
13e616 |
p_remote_sm = state_mgr_exists_other_master_sm(sm);
|
|
Packit |
13e616 |
if (p_remote_sm != NULL) {
|
|
Packit |
13e616 |
/* There is a remote SM that is master.
|
|
Packit |
13e616 |
* need to wait for that SM to relinquish control
|
|
Packit |
13e616 |
* of its portion of the subnet. C14-60.2.1.
|
|
Packit |
13e616 |
* Also - need to start polling on that SM. */
|
|
Packit |
13e616 |
CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
sm->polling_sm_guid = p_remote_sm->smi.guid;
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm,
|
|
Packit |
13e616 |
OSM_SM_SIGNAL_WAIT_FOR_HANDOVER);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
} else if (sm->polling_sm_guid) {
|
|
Packit |
13e616 |
/* Stop polling SM if it's not found */
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm,
|
|
Packit |
13e616 |
OSM_SM_SIGNAL_POLLING_TIMEOUT);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* If we are not MASTER already - this means that we are
|
|
Packit |
13e616 |
* in discovery state. call osm_sm_state_mgr with signal
|
|
Packit |
13e616 |
* DISCOVERY_COMPLETED
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING)
|
|
Packit |
13e616 |
osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVERY_COMPLETED);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_reset_switch_state_change_bit(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_pkey_mgr_process(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* try to restore SA DB (this should be before lid_mgr
|
|
Packit |
13e616 |
because we may want to disable clients reregistration
|
|
Packit |
13e616 |
when SA DB is restored) */
|
|
Packit |
13e616 |
osm_sa_db_file_load(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"PKEY setup completed - STARTING SM LID CONFIG");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_lid_mgr_process_sm(&sm->lid_mgr);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"SM LID ASSIGNMENT COMPLETE - STARTING SUBNET LID CONFIG");
|
|
Packit |
13e616 |
state_mgr_notify_lid_change(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_lid_mgr_process_subnet(&sm->lid_mgr);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* At this point we need to check the consistency of
|
|
Packit |
13e616 |
* the port_lid_tbl under the subnet. There might be
|
|
Packit |
13e616 |
* errors in it if PortInfo Set requests didn't reach
|
|
Packit |
13e616 |
* their destination. */
|
|
Packit |
13e616 |
state_mgr_check_tbl_consistency(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LID ASSIGNMENT COMPLETE - STARTING SWITCH TABLE CONFIG");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Proceed with unicast forwarding table configuration; if it fails
|
|
Packit |
13e616 |
* return early to wait for a trap or the next sweep interval.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!sm->ucast_mgr.cache_valid ||
|
|
Packit |
13e616 |
osm_ucast_cache_process(&sm->ucast_mgr)) {
|
|
Packit |
13e616 |
if (osm_ucast_mgr_process(&sm->ucast_mgr)) {
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(&sm->ucast_mgr);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_qos_setup(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* We are done setting all LFTs so clear the ignore existing.
|
|
Packit |
13e616 |
* From now on, as long as we are still master, we want to
|
|
Packit |
13e616 |
* take into account these lfts. */
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"SWITCHES CONFIGURED FOR UNICAST");
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_UCAST_ROUTING_DONE,
|
|
Packit |
13e616 |
(void *) UCAST_ROUTING_HEAVY_SWEEP);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!sm->p_subn->opt.disable_multicast) {
|
|
Packit |
13e616 |
osm_mcast_mgr_process(sm, TRUE);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"SWITCHES CONFIGURED FOR MULTICAST");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_guid_mgr_process(sm);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "ALIAS GUIDS CONFIGURED");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* The LINK_PORTS state is required since we cannot count on
|
|
Packit |
13e616 |
* the port state change MADs to succeed. This is an artifact
|
|
Packit |
13e616 |
* of the spec defining state change from state X to state X
|
|
Packit |
13e616 |
* as an error. The hardware then is not required to process
|
|
Packit |
13e616 |
* other parameters provided by the Set(PortInfo) Packet.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_link_mgr_process(sm, IB_LINK_NO_CHANGE);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LINKS PORTS CONFIGURED - SET LINKS TO ARMED STATE");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_link_mgr_process(sm, IB_LINK_ARMED);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LINKS ARMED - SET LINKS TO ACTIVE STATE");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_link_mgr_process(sm, IB_LINK_ACTIVE);
|
|
Packit |
13e616 |
if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* The sweep completed!
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Now do GSI configuration */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_congestion_control_setup(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_congestion_control_wait_pending_transactions(sm->p_subn->p_osm))
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Send trap 64 on newly discovered endports
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
state_mgr_report_new_ports(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* check switch lft buffers assignments */
|
|
Packit |
13e616 |
cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl, check_switch_lft,
|
|
Packit |
13e616 |
sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* in any case we zero this flag */
|
|
Packit |
13e616 |
sm->p_subn->coming_out_of_standby = FALSE;
|
|
Packit |
13e616 |
sm->p_subn->first_time_master_sweep = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* If there were errors - then the subnet is not really up */
|
|
Packit |
13e616 |
if (sm->p_subn->subnet_initialization_error == TRUE) {
|
|
Packit |
13e616 |
osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID,
|
|
Packit |
13e616 |
"Errors during initialization\n");
|
|
Packit |
13e616 |
OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERRORS DURING INITIALIZATION");
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
sm->p_subn->need_update = 0;
|
|
Packit |
13e616 |
osm_dump_all(sm->p_subn->p_osm);
|
|
Packit |
13e616 |
state_mgr_up_msg(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if ((OSM_LOG_IS_ACTIVE_V2(sm->p_log, OSM_LOG_VERBOSE) ||
|
|
Packit |
13e616 |
sm->p_subn->opt.sa_db_dump) &&
|
|
Packit |
13e616 |
!osm_sa_db_file_dump(sm->p_subn->p_osm))
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm,
|
|
Packit |
13e616 |
OSM_EVENT_ID_SA_DB_DUMPED,
|
|
Packit |
13e616 |
NULL);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Finally signal the subnet up event
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
cl_event_signal(&sm->subnet_up_event);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if we got a signal to force heavy sweep or errors
|
|
Packit |
13e616 |
* in the middle of the sweep - try another sweep. */
|
|
Packit |
13e616 |
if (sm->p_subn->force_heavy_sweep)
|
|
Packit |
13e616 |
osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Write a new copy of our persistent guid2mkey database */
|
|
Packit |
13e616 |
osm_db_store(sm->p_subn->p_g2m, sm->p_subn->opt.fsync_high_avail_files);
|
|
Packit |
13e616 |
osm_db_store(sm->p_subn->p_neighbor,
|
|
Packit |
13e616 |
sm->p_subn->opt.fsync_high_avail_files);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_SUBNET_UP,
|
|
Packit |
13e616 |
NULL);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void do_process_mgrp_queue(osm_sm_t * sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
if (!sm->p_subn->opt.disable_multicast) {
|
|
Packit |
13e616 |
osm_mcast_mgr_process(sm, FALSE);
|
|
Packit |
13e616 |
wait_for_pending_transactions(&sm->p_subn->p_osm->stats);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void do_process_guid_queue(osm_sm_t *sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_guid_mgr_process(sm);
|
|
Packit |
13e616 |
wait_for_pending_transactions(&sm->p_subn->p_osm->stats);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
CL_ASSERT(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received signal %s in state %s\n",
|
|
Packit |
13e616 |
osm_get_sm_signal_str(signal),
|
|
Packit |
13e616 |
osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch (signal) {
|
|
Packit |
13e616 |
case OSM_SIGNAL_SWEEP:
|
|
Packit |
13e616 |
if (!sm->p_subn->sweeping_enabled) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "sweeping disabled - "
|
|
Packit |
13e616 |
"ignoring signal %s in state %s\n",
|
|
Packit |
13e616 |
osm_get_sm_signal_str(signal),
|
|
Packit |
13e616 |
osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
do_sweep(sm);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST:
|
|
Packit |
13e616 |
do_process_mgrp_queue(sm);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
case OSM_SIGNAL_GUID_PROCESS_REQUEST:
|
|
Packit |
13e616 |
do_process_guid_queue(sm);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
CL_ASSERT(FALSE);
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3320: "
|
|
Packit |
13e616 |
"Invalid SM signal %u\n", signal);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|