|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2012 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_pi_rcv_t.
|
|
Packit |
13e616 |
* This object represents the PortInfo Receiver object.
|
|
Packit |
13e616 |
* This object is part of the opensm family of objects.
|
|
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 <string.h>
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <complib/cl_qmap.h>
|
|
Packit |
13e616 |
#include <complib/cl_passivelock.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_PORT_INFO_RCV_C
|
|
Packit |
13e616 |
#include <vendor/osm_vendor_api.h>
|
|
Packit |
13e616 |
#include <opensm/osm_madw.h>
|
|
Packit |
13e616 |
#include <opensm/osm_log.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_subnet.h>
|
|
Packit |
13e616 |
#include <opensm/osm_mad_pool.h>
|
|
Packit |
13e616 |
#include <opensm/osm_msgdef.h>
|
|
Packit |
13e616 |
#include <opensm/osm_helper.h>
|
|
Packit |
13e616 |
#include <opensm/osm_pkey.h>
|
|
Packit |
13e616 |
#include <opensm/osm_remote_sm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_opensm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_ucast_mgr.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void pi_rcv_check_and_fix_lid(osm_log_t * log, ib_port_info_t * pi,
|
|
Packit |
13e616 |
osm_physp_t * p)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (PF(cl_ntoh16(pi->base_lid) > IB_LID_UCAST_END_HO)) {
|
|
Packit |
13e616 |
OSM_LOG(log, OSM_LOG_ERROR, "ERR 0F04: "
|
|
Packit |
13e616 |
"Got invalid base LID %u from the network. "
|
|
Packit |
13e616 |
"Corrected to %u\n", cl_ntoh16(pi->base_lid),
|
|
Packit |
13e616 |
cl_ntoh16(p->port_info.base_lid));
|
|
Packit |
13e616 |
pi->base_lid = p->port_info.base_lid;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void pi_rcv_process_endport(IN osm_sm_t * sm, IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN const ib_port_info_t * p_pi)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
int extended;
|
|
Packit |
13e616 |
uint8_t rate, mtu, mpb;
|
|
Packit |
13e616 |
unsigned data_vls;
|
|
Packit |
13e616 |
cl_qmap_t *p_sm_tbl;
|
|
Packit |
13e616 |
osm_remote_sm_t *p_sm;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* HACK extended port 0 should be handled too! */
|
|
Packit |
13e616 |
if (osm_physp_get_port_num(p_physp) != 0 &&
|
|
Packit |
13e616 |
ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN) {
|
|
Packit |
13e616 |
/* track the minimal endport MTU, rate, and operational VLs */
|
|
Packit |
13e616 |
mtu = ib_port_info_get_mtu_cap(p_pi);
|
|
Packit |
13e616 |
if (mtu < sm->p_subn->min_ca_mtu) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Setting endport minimal MTU to:%u defined by port:0x%"
|
|
Packit |
13e616 |
PRIx64 "\n", mtu, cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
sm->p_subn->min_ca_mtu = mtu;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
|
|
Packit |
13e616 |
rate = ib_port_info_compute_rate(p_pi, extended);
|
|
Packit |
13e616 |
if (ib_path_compare_rates(rate, sm->p_subn->min_ca_rate) < 0) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Setting endport minimal rate to:%u defined by port:0x%"
|
|
Packit |
13e616 |
PRIx64 "\n", rate, cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
sm->p_subn->min_ca_rate = rate;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1);
|
|
Packit |
13e616 |
if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1))
|
|
Packit |
13e616 |
data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1);
|
|
Packit |
13e616 |
if (data_vls >= IB_MAX_NUM_VLS)
|
|
Packit |
13e616 |
data_vls = IB_MAX_NUM_VLS - 1;
|
|
Packit |
13e616 |
if ((uint8_t)data_vls < sm->p_subn->min_data_vls) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Setting endport minimal data VLs to:%u defined by port:0x%"
|
|
Packit |
13e616 |
PRIx64 "\n", data_vls, cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
sm->p_subn->min_data_vls = data_vls;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Check M_Key vs M_Key protect, can we control the port ? */
|
|
Packit |
13e616 |
mpb = ib_port_info_get_mpb(p_pi);
|
|
Packit |
13e616 |
if (mpb > 0 && p_pi->m_key == 0) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"Port 0x%" PRIx64 " has unknown M_Key, protection level %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid), mpb);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (port_guid != sm->p_subn->sm_port_guid) {
|
|
Packit |
13e616 |
p_sm_tbl = &sm->p_subn->sm_guid_tbl;
|
|
Packit |
13e616 |
if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Before querying the SM - we want to make sure we
|
|
Packit |
13e616 |
* clean its state, so if the querying fails we
|
|
Packit |
13e616 |
* recognize that this SM is not active.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_sm =
|
|
Packit |
13e616 |
(osm_remote_sm_t *) cl_qmap_get(p_sm_tbl,
|
|
Packit |
13e616 |
port_guid);
|
|
Packit |
13e616 |
if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
|
|
Packit |
13e616 |
/* clean it up */
|
|
Packit |
13e616 |
p_sm->smi.pri_state =
|
|
Packit |
13e616 |
0xF0 & p_sm->smi.pri_state;
|
|
Packit |
13e616 |
if (sm->p_subn->opt.ignore_other_sm)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Ignoring SM on port 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
else {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Detected another SM. Requesting SMInfo "
|
|
Packit |
13e616 |
"from port 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
This port indicates it's an SM and
|
|
Packit |
13e616 |
it's not our own port.
|
|
Packit |
13e616 |
Acquire the SMInfo Attribute.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
memset(&context, 0, sizeof(context));
|
|
Packit |
13e616 |
context.smi_context.set_method = FALSE;
|
|
Packit |
13e616 |
context.smi_context.port_guid = port_guid;
|
|
Packit |
13e616 |
status = osm_req_get(sm,
|
|
Packit |
13e616 |
osm_physp_get_dr_path_ptr
|
|
Packit |
13e616 |
(p_physp),
|
|
Packit |
13e616 |
IB_MAD_ATTR_SM_INFO, 0,
|
|
Packit |
13e616 |
FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE,
|
|
Packit |
13e616 |
&context);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 0F05: "
|
|
Packit |
13e616 |
"Failure requesting SMInfo (%s) "
|
|
Packit |
13e616 |
"from port 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
ib_get_err_str(status),
|
|
Packit |
13e616 |
cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
p_sm =
|
|
Packit |
13e616 |
(osm_remote_sm_t *) cl_qmap_remove(p_sm_tbl,
|
|
Packit |
13e616 |
port_guid);
|
|
Packit |
13e616 |
if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
|
|
Packit |
13e616 |
free(p_sm);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
The plock must be held before calling this function.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void pi_rcv_process_switch_port0(IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN ib_port_info_t * p_pi)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
uint8_t port, num_ports;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_physp->need_update)
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Update the PortInfo attribute */
|
|
Packit |
13e616 |
osm_physp_set_port_info(p_physp, p_pi, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Determine if base switch port 0 */
|
|
Packit |
13e616 |
if (p_node->sw &&
|
|
Packit |
13e616 |
!ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
|
|
Packit |
13e616 |
/* PortState is not used on BSP0 but just in case it is DOWN */
|
|
Packit |
13e616 |
p_physp->port_info = *p_pi;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Now, query PortInfo for the switch external ports */
|
|
Packit |
13e616 |
num_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.pi_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
context.pi_context.set_method = FALSE;
|
|
Packit |
13e616 |
context.pi_context.light_sweep = FALSE;
|
|
Packit |
13e616 |
context.pi_context.active_transition = FALSE;
|
|
Packit |
13e616 |
context.pi_context.client_rereg = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (port = 1; port < num_ports; port++) {
|
|
Packit |
13e616 |
status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
|
|
Packit |
13e616 |
IB_MAD_ATTR_PORT_INFO, cl_hton32(port),
|
|
Packit |
13e616 |
FALSE,
|
|
Packit |
13e616 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F16: "
|
|
Packit |
13e616 |
"Failure initiating PortInfo request (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pi_rcv_process_endport(sm, p_physp, p_pi);
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
The plock must be held before calling this function.
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static void pi_rcv_process_switch_ext_port(IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN ib_port_info_t * p_pi)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
osm_physp_t *p_remote_physp, *physp0;
|
|
Packit |
13e616 |
osm_node_t *p_remote_node;
|
|
Packit |
13e616 |
ib_net64_t m_key;
|
|
Packit |
13e616 |
unsigned data_vls;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
uint8_t remote_port_num;
|
|
Packit |
13e616 |
osm_dr_path_t path;
|
|
Packit |
13e616 |
int mlnx_epi_supported = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Check the state of the physical port.
|
|
Packit |
13e616 |
If there appears to be something on the other end of the wire,
|
|
Packit |
13e616 |
then ask for NodeInfo. Ignore the switch management port.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
port_num = osm_physp_get_port_num(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->opt.fdr10)
|
|
Packit |
13e616 |
mlnx_epi_supported = is_mlnx_ext_port_info_supported(
|
|
Packit |
13e616 |
ib_node_info_get_vendor_id(&p_node->node_info),
|
|
Packit |
13e616 |
p_node->node_info.device_id);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch,
|
|
Packit |
13e616 |
and we got switchInfo of our local switch. Do not continue
|
|
Packit |
13e616 |
probing through the switch. */
|
|
Packit |
13e616 |
switch (ib_port_info_get_port_state(p_pi)) {
|
|
Packit |
13e616 |
case IB_LINK_DOWN:
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if (p_remote_physp) {
|
|
Packit |
13e616 |
p_remote_node =
|
|
Packit |
13e616 |
osm_physp_get_node_ptr(p_remote_physp);
|
|
Packit |
13e616 |
remote_port_num =
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Unlinking local node 0x%" PRIx64
|
|
Packit |
13e616 |
", port %u"
|
|
Packit |
13e616 |
"\n\t\t\t\tand remote node 0x%" PRIx64
|
|
Packit |
13e616 |
", port %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit |
13e616 |
(p_node)), port_num,
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit |
13e616 |
(p_remote_node)),
|
|
Packit |
13e616 |
remote_port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->ucast_mgr.cache_valid)
|
|
Packit |
13e616 |
osm_ucast_cache_add_link(&sm->ucast_mgr,
|
|
Packit |
13e616 |
p_physp,
|
|
Packit |
13e616 |
p_remote_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_node_unlink(p_node, (uint8_t) port_num,
|
|
Packit |
13e616 |
p_remote_node,
|
|
Packit |
13e616 |
(uint8_t) remote_port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
case IB_LINK_INIT:
|
|
Packit |
13e616 |
case IB_LINK_ARMED:
|
|
Packit |
13e616 |
case IB_LINK_ACTIVE:
|
|
Packit |
13e616 |
physp0 = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit |
13e616 |
if (mlnx_epi_supported) {
|
|
Packit |
13e616 |
m_key = ib_port_info_get_m_key(&physp0->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.pi_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
context.pi_context.set_method = FALSE;
|
|
Packit |
13e616 |
context.pi_context.light_sweep = FALSE;
|
|
Packit |
13e616 |
context.pi_context.active_transition = FALSE;
|
|
Packit |
13e616 |
context.pi_context.client_rereg = FALSE;
|
|
Packit |
13e616 |
status = osm_req_get(sm,
|
|
Packit |
13e616 |
osm_physp_get_dr_path_ptr(p_physp),
|
|
Packit |
13e616 |
IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
|
|
Packit |
13e616 |
cl_hton32(port_num), FALSE, m_key,
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F11: "
|
|
Packit |
13e616 |
"Failure initiating MLNX ExtPortInfo request (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (sm->p_subn->in_sweep_hop_0 == FALSE) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
To avoid looping forever, only probe the port if it
|
|
Packit |
13e616 |
is NOT the port that responded to the SMP.
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Request node info from the other end of this link:
|
|
Packit |
13e616 |
1) Copy the current path from the parent node.
|
|
Packit |
13e616 |
2) Extend the path to the next hop thru this port.
|
|
Packit |
13e616 |
3) Request node info with the new path
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_pi->local_port_num !=
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp)) {
|
|
Packit |
13e616 |
path = *osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_dr_path_extend(&path,
|
|
Packit |
13e616 |
osm_physp_get_port_num
|
|
Packit |
13e616 |
(p_physp))) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 0F08: "
|
|
Packit |
13e616 |
"DR path with hop count %d couldn't be extended\n",
|
|
Packit |
13e616 |
path.hop_count);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
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 =
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = osm_req_get(sm, &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 |
|
|
Packit |
13e616 |
if (status != IB_SUCCESS)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 0F02: "
|
|
Packit |
13e616 |
"Failure initiating NodeInfo request (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Skipping SMP responder port %u\n",
|
|
Packit |
13e616 |
p_pi->local_port_num);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: "
|
|
Packit |
13e616 |
"Unknown link state = %u, port = %u\n",
|
|
Packit |
13e616 |
ib_port_info_get_port_state(p_pi),
|
|
Packit |
13e616 |
p_pi->local_port_num);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw &&
|
|
Packit |
13e616 |
!ib_switch_info_get_state_change(&p_node->sw->switch_info) &&
|
|
Packit |
13e616 |
p_node->sw->need_update == 1)
|
|
Packit |
13e616 |
p_node->sw->need_update = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_physp->need_update)
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Update the PortInfo attribute.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
osm_physp_set_port_info(p_physp, p_pi, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if (p_remote_physp) {
|
|
Packit |
13e616 |
p_remote_node = osm_physp_get_node_ptr(p_remote_physp);
|
|
Packit |
13e616 |
if (p_remote_node->sw) {
|
|
Packit |
13e616 |
data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1);
|
|
Packit |
13e616 |
if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1))
|
|
Packit |
13e616 |
data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1);
|
|
Packit |
13e616 |
if (data_vls >= IB_MAX_NUM_VLS)
|
|
Packit |
13e616 |
data_vls = IB_MAX_NUM_VLS - 1;
|
|
Packit |
13e616 |
if ((uint8_t)data_vls < sm->p_subn->min_sw_data_vls) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Setting switch port minimal data VLs "
|
|
Packit |
13e616 |
"to:%u defined by node:0x%"
|
|
Packit |
13e616 |
PRIx64 ", port:%u\n", data_vls,
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
sm->p_subn->min_sw_data_vls = data_vls;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN ib_port_info_t * p_pi)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
UNUSED_PARAM(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_physp_set_port_info(p_physp, p_pi, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
pi_rcv_process_endport(sm, p_physp, p_pi);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#define IBM_VENDOR_ID (0x5076)
|
|
Packit |
13e616 |
static void get_pkey_table(IN osm_log_t * p_log, IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_node_t * p_node, IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
osm_dr_path_t path;
|
|
Packit |
13e616 |
osm_physp_t *physp0;
|
|
Packit |
13e616 |
ib_net64_t m_key;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
uint16_t block_num, max_blocks;
|
|
Packit |
13e616 |
uint32_t attr_mod_ho;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
path = *osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.pkey_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
context.pkey_context.set_method = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_num = p_physp->port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_node->sw || port_num == 0)
|
|
Packit |
13e616 |
/* The maximum blocks is defined by the node info partition cap
|
|
Packit |
13e616 |
for CA, router, and switch management ports. */
|
|
Packit |
13e616 |
max_blocks =
|
|
Packit |
13e616 |
(cl_ntoh16(p_node->node_info.partition_cap) +
|
|
Packit |
13e616 |
IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
|
|
Packit |
13e616 |
/ IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
|
|
Packit |
13e616 |
else {
|
|
Packit |
13e616 |
/* This is a switch, and not a management port. The maximum blocks
|
|
Packit |
13e616 |
is defined in the switch info partition enforcement cap. */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Check for IBM eHCA firmware defect in reporting partition enforcement cap */
|
|
Packit |
13e616 |
if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) ==
|
|
Packit |
13e616 |
IBM_VENDOR_ID)
|
|
Packit |
13e616 |
p_node->sw->switch_info.enforce_cap = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Bail out if this is a switch with no partition enforcement capability */
|
|
Packit |
13e616 |
if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) +
|
|
Packit |
13e616 |
IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
|
|
Packit |
13e616 |
1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp->pkeys.rcv_blocks_cnt = max_blocks;
|
|
Packit |
13e616 |
for (block_num = 0; block_num < max_blocks; block_num++) {
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp) == 0) {
|
|
Packit |
13e616 |
attr_mod_ho = block_num;
|
|
Packit |
13e616 |
m_key = ib_port_info_get_m_key(&p_physp->port_info);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
attr_mod_ho = block_num | (port_num << 16);
|
|
Packit |
13e616 |
physp0 = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit |
13e616 |
m_key = ib_port_info_get_m_key(&physp0->port_info);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
status = osm_req_get(sm, &path, IB_MAD_ATTR_P_KEY_TABLE,
|
|
Packit |
13e616 |
cl_hton32(attr_mod_ho), FALSE,
|
|
Packit |
13e616 |
m_key, 0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (status != IB_SUCCESS) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0F12: "
|
|
Packit |
13e616 |
"Failure initiating PKeyTable request (%s)\n",
|
|
Packit |
13e616 |
ib_get_err_str(status));
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void pi_rcv_get_pkey_slvl_vla_tables(IN osm_sm_t * sm,
|
|
Packit |
13e616 |
IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
get_pkey_table(sm->p_log, sm, p_node, p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int osm_pi_rcv_update_self(IN osm_sm_t *sm, IN osm_physp_t *p_physp,
|
|
Packit |
13e616 |
IN ib_port_info_t *p_pi)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->need_update || p_physp->need_update > 1 ||
|
|
Packit |
13e616 |
ib_port_info_get_port_state(p_pi) == IB_LINK_INIT)
|
|
Packit |
13e616 |
return 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void pi_rcv_process_set(IN osm_sm_t * sm, IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN uint8_t port_num, IN osm_madw_t * p_madw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
ib_smp_t *p_smp;
|
|
Packit |
13e616 |
ib_port_info_t *p_pi;
|
|
Packit |
13e616 |
osm_pi_context_t *p_context;
|
|
Packit |
13e616 |
osm_log_level_t level;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_context = osm_madw_get_pi_context_ptr(p_madw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_smp = osm_madw_get_smp_ptr(p_madw);
|
|
Packit |
13e616 |
p_pi = ib_smp_get_payload_ptr(p_smp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* check for error */
|
|
Packit |
13e616 |
if (cl_ntoh16(p_smp->status) & 0x7fff) {
|
|
Packit |
13e616 |
/* If port already ACTIVE, don't treat status 7 as error */
|
|
Packit |
13e616 |
if (p_context->active_transition &&
|
|
Packit |
13e616 |
(cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) {
|
|
Packit |
13e616 |
level = OSM_LOG_INFO;
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"Received error status 0x%x for SetResp() during ACTIVE transition\n",
|
|
Packit |
13e616 |
cl_ntoh16(p_smp->status) & 0x7fff);
|
|
Packit |
13e616 |
/* Should there be a subsequent Get to validate that port is ACTIVE ? */
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
level = OSM_LOG_ERROR;
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F10: "
|
|
Packit |
13e616 |
"Received error status for SetResp()\n");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
osm_dump_port_info_v2(sm->p_log, osm_node_get_node_guid(p_node),
|
|
Packit |
13e616 |
port_guid, port_num, p_pi, FILE_ID, level);
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
osm_physp_set_port_info(p_physp, p_pi, sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Received logical SetResp() for GUID 0x%" PRIx64
|
|
Packit |
13e616 |
", port num %u"
|
|
Packit |
13e616 |
"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
|
|
Packit |
13e616 |
" TID 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid), port_num,
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)),
|
|
Packit |
13e616 |
cl_ntoh64(p_smp->trans_id));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int osm_pi_rcv_update_neighbor(IN osm_physp_t *p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p_rem_physp = p_physp->p_remote_physp;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Our own port - this is the only case where CA port
|
|
Packit |
13e616 |
* is discovered before its' neighbor port
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (!p_rem_physp)
|
|
Packit |
13e616 |
return p_physp->need_update;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = osm_physp_get_node_ptr(p_rem_physp);
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* CA/RTR to CA/RTR connection */
|
|
Packit |
13e616 |
if (!p_node->sw)
|
|
Packit |
13e616 |
return p_physp->need_update;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return (ib_switch_info_get_state_change(&p_node->sw->switch_info) ? 1 : p_physp->need_update);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_pi_rcv_process(IN void *context, IN void *data)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_sm_t *sm = context;
|
|
Packit |
13e616 |
osm_madw_t *p_madw = data;
|
|
Packit |
13e616 |
ib_port_info_t *p_pi;
|
|
Packit |
13e616 |
ib_smp_t *p_smp;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
osm_dr_path_t *p_dr_path;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_pi_context_t *p_context;
|
|
Packit |
13e616 |
ib_net64_t port_guid, node_guid;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(sm);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_madw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_smp = osm_madw_get_smp_ptr(p_madw);
|
|
Packit |
13e616 |
p_context = osm_madw_get_pi_context_ptr(p_madw);
|
|
Packit |
13e616 |
p_pi = ib_smp_get_payload_ptr(p_smp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Attribute modifier has already been validated upon MAD receive,
|
|
Packit |
13e616 |
* which means that port_num has to be valid - it originated from
|
|
Packit |
13e616 |
* the request attribute modifier.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = p_context->port_guid;
|
|
Packit |
13e616 |
node_guid = p_context->node_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_dump_port_info_v2(sm->p_log, node_guid, port_guid, port_num, p_pi,
|
|
Packit |
13e616 |
FILE_ID, OSM_LOG_DEBUG);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* On receipt of client reregister, clear the reregister bit so
|
|
Packit |
13e616 |
reregistering won't be sent again and again */
|
|
Packit |
13e616 |
if (p_context->set_method &&
|
|
Packit |
13e616 |
(ib_port_info_get_client_rereg(p_pi) || p_context->client_rereg)) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Client reregister received on response\n");
|
|
Packit |
13e616 |
ib_port_info_set_client_rereg(p_pi, 0);
|
|
Packit |
13e616 |
p_context->client_rereg = FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
we might get a response during a light sweep looking for a change in
|
|
Packit |
13e616 |
the status of a remote port that did not respond in earlier sweeps.
|
|
Packit |
13e616 |
So if the context of the Get was light_sweep - we do not need to
|
|
Packit |
13e616 |
do anything with the response - just flag that we need a heavy sweep
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_context->light_sweep == TRUE) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Got light sweep response from remote port of parent node "
|
|
Packit |
13e616 |
"GUID 0x%" PRIx64 " port 0x%016" PRIx64
|
|
Packit |
13e616 |
", Commencing heavy sweep\n",
|
|
Packit |
13e616 |
cl_ntoh64(node_guid), cl_ntoh64(port_guid));
|
|
Packit |
13e616 |
sm->p_subn->force_heavy_sweep = TRUE;
|
|
Packit |
13e616 |
sm->p_subn->ignore_existing_lfts = TRUE;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
|
|
Packit |
13e616 |
if (PF(!p_port)) {
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
|
|
Packit |
13e616 |
"No port object for port with GUID 0x%" PRIx64
|
|
Packit |
13e616 |
"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
|
|
Packit |
13e616 |
", TID 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid),
|
|
Packit |
13e616 |
cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
|
|
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 |
if (PF(p_pi->local_port_num > p_node->node_info.num_ports)) {
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F15: "
|
|
Packit |
13e616 |
"Received PortInfo for port GUID 0x%" PRIx64 " is "
|
|
Packit |
13e616 |
"non-compliant and is being ignored since the "
|
|
Packit |
13e616 |
"local port num %u > num ports %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(port_guid), p_pi->local_port_num,
|
|
Packit |
13e616 |
p_node->node_info.num_ports);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
If we were setting the PortInfo, then receiving
|
|
Packit |
13e616 |
this attribute was not part of sweeping the subnet.
|
|
Packit |
13e616 |
In this case, just update the PortInfo attribute.
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
In an unfortunate blunder, the IB spec defines the
|
|
Packit |
13e616 |
return method for Set() as a GetResp(). Thus, we can't
|
|
Packit |
13e616 |
use the method (what would have been SetResp()) to determine
|
|
Packit |
13e616 |
our course of action. So, we have to carry this extra
|
|
Packit |
13e616 |
boolean around to determine if we were doing Get() or Set().
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_context->set_method)
|
|
Packit |
13e616 |
pi_rcv_process_set(sm, p_node, port_num, p_madw);
|
|
Packit |
13e616 |
else {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
This PortInfo arrived because we did a Get() method,
|
|
Packit |
13e616 |
most likely due to a subnet sweep in progress.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Discovered port num %u with GUID 0x%" PRIx64
|
|
Packit |
13e616 |
" for parent node GUID 0x%" PRIx64
|
|
Packit |
13e616 |
", TID 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
port_num, cl_ntoh64(port_guid),
|
|
Packit |
13e616 |
cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Update the directed route path to this port
|
|
Packit |
13e616 |
in case the old path is no longer usable. */
|
|
Packit |
13e616 |
p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit |
13e616 |
osm_dr_path_init(p_dr_path, p_smp->hop_count,
|
|
Packit |
13e616 |
p_smp->initial_path);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp->need_update = osm_pi_rcv_update_self(sm, p_physp, p_pi);
|
|
Packit |
13e616 |
|
|
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 |
if (!p_node->physp_discovered[port_num]) {
|
|
Packit |
13e616 |
p_port->discovery_count++;
|
|
Packit |
13e616 |
p_node->physp_discovered[port_num] = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
p_physp->need_update = osm_pi_rcv_update_neighbor(p_physp);
|
|
Packit |
13e616 |
pi_rcv_process_ca_or_router_port(sm, p_node, p_physp,
|
|
Packit |
13e616 |
p_pi);
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
case IB_NODE_TYPE_SWITCH:
|
|
Packit |
13e616 |
if (!p_node->physp_discovered[port_num]) {
|
|
Packit |
13e616 |
p_port->discovery_count++;
|
|
Packit |
13e616 |
p_node->physp_discovered[port_num] = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (port_num == 0)
|
|
Packit |
13e616 |
pi_rcv_process_switch_port0(sm, p_node,
|
|
Packit |
13e616 |
p_physp, p_pi);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
pi_rcv_process_switch_ext_port(sm, p_node,
|
|
Packit |
13e616 |
p_physp, p_pi);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) {
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
default:
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
|
|
Packit |
13e616 |
"Unknown node type %u with GUID 0x%" PRIx64
|
|
Packit |
13e616 |
"\n", osm_node_get_type(p_node),
|
|
Packit |
13e616 |
cl_ntoh64(node_guid));
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Get the tables on the physp.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_physp->need_update || (p_node->sw &&
|
|
Packit |
13e616 |
p_node->sw->need_update))
|
|
Packit |
13e616 |
pi_rcv_get_pkey_slvl_vla_tables(sm, p_node, p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Release the lock before jumping here!!
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
}
|