Blame opensm/osm_node_info_rcv.c

Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2009 HNR Consulting. All rights reserved.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * This software is available to you under a choice of one of two
Packit Service 54dbc3
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit Service 54dbc3
 * General Public License (GPL) Version 2, available from the file
Packit Service 54dbc3
 * COPYING in the main directory of this source tree, or the
Packit Service 54dbc3
 * OpenIB.org BSD license below:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *     Redistribution and use in source and binary forms, with or
Packit Service 54dbc3
 *     without modification, are permitted provided that the following
Packit Service 54dbc3
 *     conditions are met:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions of source code must retain the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions in binary form must reproduce the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer in the documentation and/or other materials
Packit Service 54dbc3
 *        provided with the distribution.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit Service 54dbc3
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 54dbc3
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit Service 54dbc3
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit Service 54dbc3
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit Service 54dbc3
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 54dbc3
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit Service 54dbc3
 * SOFTWARE.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Abstract:
Packit Service 54dbc3
 *    Implementation of osm_ni_rcv_t.
Packit Service 54dbc3
 * This object represents the NodeInfo Receiver object.
Packit Service 54dbc3
 * This object is part of the opensm family of objects.
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
#if HAVE_CONFIG_H
Packit Service 54dbc3
#  include <config.h>
Packit Service 54dbc3
#endif				/* HAVE_CONFIG_H */
Packit Service 54dbc3
Packit Service 54dbc3
#include <stdlib.h>
Packit Service 54dbc3
#include <string.h>
Packit Service 54dbc3
#include <iba/ib_types.h>
Packit Service 54dbc3
#include <complib/cl_qmap.h>
Packit Service 54dbc3
#include <complib/cl_passivelock.h>
Packit Service 54dbc3
#include <complib/cl_debug.h>
Packit Service 54dbc3
#include <opensm/osm_file_ids.h>
Packit Service 54dbc3
#define FILE_ID OSM_FILE_NODE_INFO_RCV_C
Packit Service 54dbc3
#include <opensm/osm_madw.h>
Packit Service 54dbc3
#include <opensm/osm_log.h>
Packit Service 54dbc3
#include <opensm/osm_node.h>
Packit Service 54dbc3
#include <opensm/osm_subnet.h>
Packit Service 54dbc3
#include <opensm/osm_router.h>
Packit Service 54dbc3
#include <opensm/osm_mad_pool.h>
Packit Service 54dbc3
#include <opensm/osm_helper.h>
Packit Service 54dbc3
#include <opensm/osm_msgdef.h>
Packit Service 54dbc3
#include <opensm/osm_opensm.h>
Packit Service 54dbc3
#include <opensm/osm_ucast_mgr.h>
Packit Service 54dbc3
#include <opensm/osm_db_pack.h>
Packit Service 54dbc3
Packit Service 54dbc3
static void report_duplicated_guid(IN osm_sm_t * sm, osm_physp_t * p_physp,
Packit Service 54dbc3
				   osm_node_t * p_neighbor_node,
Packit Service 54dbc3
				   const uint8_t port_num)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_physp_t *p_old, *p_new;
Packit Service 54dbc3
	osm_dr_path_t path;
Packit Service 54dbc3
Packit Service 54dbc3
	p_old = p_physp->p_remote_physp;
Packit Service 54dbc3
	p_new = osm_node_get_physp_ptr(p_neighbor_node, port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(sm->p_log, OSM_LOG_SYS | OSM_LOG_ERROR, "ERR 0D01: "
Packit Service 54dbc3
		"Found duplicated node GUID.\n"
Packit Service 54dbc3
		"Node 0x%" PRIx64 " port %u is reachable from remote node "
Packit Service 54dbc3
		"0x%" PRIx64 " port %u and remote node 0x%" PRIx64 " port %u.\n"
Packit Service 54dbc3
		"Paths are:\n",
Packit Service 54dbc3
		cl_ntoh64(p_physp->p_node->node_info.node_guid),
Packit Service 54dbc3
		p_physp->port_num,
Packit Service 54dbc3
		p_old ? cl_ntoh64(p_old->p_node->node_info.node_guid) : 0,
Packit Service 54dbc3
		p_old ? p_old->port_num : 0,
Packit Service 54dbc3
		p_new ? cl_ntoh64(p_new->p_node->node_info.node_guid) : 0,
Packit Service 54dbc3
		p_new ? p_new->port_num : 0);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
			    FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
Packit Service 54dbc3
	path = *osm_physp_get_dr_path_ptr(p_new);
Packit Service 54dbc3
	if (osm_dr_path_extend(&path, port_num))
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D05: "
Packit Service 54dbc3
			"DR path with hop count %d couldn't be extended\n",
Packit Service 54dbc3
			path.hop_count);
Packit Service 54dbc3
	osm_dump_dr_path_v2(sm->p_log, &path, FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void requery_dup_node_info(IN osm_sm_t * sm, osm_physp_t * p_physp,
Packit Service 54dbc3
				  unsigned count)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_dr_path_t path;
Packit Service 54dbc3
	cl_status_t status;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p_physp->p_remote_physp) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0D: "
Packit Service 54dbc3
			"DR path couldn't be extended due to NULL remote physp\n");
Packit Service 54dbc3
		return;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	path = *osm_physp_get_dr_path_ptr(p_physp->p_remote_physp);
Packit Service 54dbc3
	if (osm_dr_path_extend(&path, p_physp->p_remote_physp->port_num)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D08: "
Packit Service 54dbc3
			"DR path with hop count %d couldn't be extended\n",
Packit Service 54dbc3
			path.hop_count);
Packit Service 54dbc3
		return;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	context.ni_context.node_guid =
Packit Service 54dbc3
	    p_physp->p_remote_physp->p_node->node_info.port_guid;
Packit Service 54dbc3
	context.ni_context.port_num = p_physp->p_remote_physp->port_num;
Packit Service 54dbc3
	context.ni_context.dup_node_guid = p_physp->p_node->node_info.node_guid;
Packit Service 54dbc3
	context.ni_context.dup_port_num = p_physp->port_num;
Packit Service 54dbc3
	context.ni_context.dup_count = count;
Packit Service 54dbc3
Packit Service 54dbc3
	status = osm_req_get(sm, &path, IB_MAD_ATTR_NODE_INFO, 0,
Packit Service 54dbc3
			     TRUE, 0, 0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D02: "
Packit Service 54dbc3
			"Failure initiating NodeInfo request (%s)\n",
Packit Service 54dbc3
			ib_get_err_str(status));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_set_links(IN osm_sm_t * sm, osm_node_t * p_node,
Packit Service 54dbc3
			     const uint8_t port_num,
Packit Service 54dbc3
			     const osm_ni_context_t * p_ni_context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_node_t *p_neighbor_node;
Packit Service 54dbc3
	osm_physp_t *p_physp, *p_remote_physp;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   A special case exists in which the node we're trying to
Packit Service 54dbc3
	   link is our own node.  In this case, the guid value in
Packit Service 54dbc3
	   the ni_context will be zero.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_ni_context->node_guid == 0) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Nothing to link for our own node 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_neighbor_node = osm_get_node_by_guid(sm->p_subn,
Packit Service 54dbc3
					       p_ni_context->node_guid);
Packit Service 54dbc3
	if (PF(!p_neighbor_node)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D10: "
Packit Service 54dbc3
			"Unexpected removal of neighbor node 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni_context->node_guid));
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* When setting the link, ports on both
Packit Service 54dbc3
	   sides of the link should be initialized */
Packit Service 54dbc3
	CL_ASSERT(osm_node_link_has_valid_ports(p_node, port_num,
Packit Service 54dbc3
						p_neighbor_node,
Packit Service 54dbc3
						p_ni_context->port_num));
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_node_link_exists(p_node, port_num,
Packit Service 54dbc3
				 p_neighbor_node, p_ni_context->port_num)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Link already exists\n");
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
	if (!p_physp) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD0E: "
Packit Service 54dbc3
			"Failed to find physp for port %d of Node GUID 0x%"
Packit Service 54dbc3
			PRIx64 "\n", port_num,
Packit Service 54dbc3
			cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * If the link went UP, after we already discovered it, we shouldn't
Packit Service 54dbc3
	 * set the link between the ports and resweep.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (osm_physp_get_port_state(p_physp) == IB_LINK_DOWN &&
Packit Service 54dbc3
	    p_node->physp_discovered[port_num]) {
Packit Service 54dbc3
		/* Link down on another side. Don't create a link*/
Packit Service 54dbc3
		p_node->physp_discovered[port_num] = 0;
Packit Service 54dbc3
		sm->p_subn->force_heavy_sweep = TRUE;
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_node_has_any_link(p_node, port_num) &&
Packit Service 54dbc3
	    sm->p_subn->force_heavy_sweep == FALSE &&
Packit Service 54dbc3
	    (!p_ni_context->dup_count ||
Packit Service 54dbc3
	     (p_ni_context->dup_node_guid == osm_node_get_node_guid(p_node) &&
Packit Service 54dbc3
	      p_ni_context->dup_port_num == port_num))) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Uh oh...
Packit Service 54dbc3
		   This could be reconnected ports, but also duplicated GUID
Packit Service 54dbc3
		   (2 nodes have the same guid) or a 12x link with lane reversal
Packit Service 54dbc3
		   that is not configured correctly.
Packit Service 54dbc3
		   We will try to recover by querying NodeInfo again.
Packit Service 54dbc3
		   In order to catch even fast port moving to new location(s)
Packit Service 54dbc3
		   and back we will count up to 5.
Packit Service 54dbc3
		   Some crazy reconnections (newly created switch loop right
Packit Service 54dbc3
		   before targeted CA) will not be catched this way. So in worst
Packit Service 54dbc3
		   case - report GUID duplication and request new discovery.
Packit Service 54dbc3
		   When switch node is targeted NodeInfo querying will be done
Packit Service 54dbc3
		   in opposite order, this is much stronger check, unfortunately
Packit Service 54dbc3
		   it is impossible with CAs.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
		if (!p_physp) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD0F: "
Packit Service 54dbc3
				"Failed to find physp for port %d of Node GUID 0x%"
Packit Service 54dbc3
				PRIx64 "\n", port_num,
Packit Service 54dbc3
				cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
			goto _exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_ni_context->dup_count > 5) {
Packit Service 54dbc3
			report_duplicated_guid(sm, p_physp, p_neighbor_node,
Packit Service 54dbc3
					       p_ni_context->port_num);
Packit Service 54dbc3
			sm->p_subn->force_heavy_sweep = TRUE;
Packit Service 54dbc3
		} else if (p_node->sw)
Packit Service 54dbc3
			requery_dup_node_info(sm, p_physp->p_remote_physp,
Packit Service 54dbc3
					      p_ni_context->dup_count + 1);
Packit Service 54dbc3
		else
Packit Service 54dbc3
			requery_dup_node_info(sm, p_physp,
Packit Service 54dbc3
					      p_ni_context->dup_count + 1);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   When there are only two nodes with exact same guids (connected back
Packit Service 54dbc3
	   to back) - the previous check for duplicated guid will not catch
Packit Service 54dbc3
	   them. But the link will be from the port to itself...
Packit Service 54dbc3
	   Enhanced Port 0 is an exception to this
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (osm_node_get_node_guid(p_node) == p_ni_context->node_guid &&
Packit Service 54dbc3
	    port_num == p_ni_context->port_num &&
Packit Service 54dbc3
	    port_num != 0 && cl_qmap_count(&sm->p_subn->sw_guid_tbl) == 0) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Duplicate GUID found by link from a port to itself:"
Packit Service 54dbc3
			"node 0x%" PRIx64 ", port number %u\n",
Packit Service 54dbc3
			cl_ntoh64(osm_node_get_node_guid(p_node)), port_num);
Packit Service 54dbc3
		p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
		if (!p_physp) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1D: "
Packit Service 54dbc3
				"Failed to find physp for port %d of Node GUID 0x%"
Packit Service 54dbc3
				PRIx64 "\n", port_num,
Packit Service 54dbc3
				cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
			goto _exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
				    FILE_ID, OSM_LOG_VERBOSE);
Packit Service 54dbc3
Packit Service 54dbc3
		if (sm->p_subn->opt.exit_on_fatal == TRUE) {
Packit Service 54dbc3
			osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID,
Packit Service 54dbc3
				   "Errors on subnet. Duplicate GUID found "
Packit Service 54dbc3
				   "by link from a port to itself. "
Packit Service 54dbc3
				   "See verbose opensm.log for more details\n");
Packit Service 54dbc3
			exit(1);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Creating new link between:\n\t\t\t\tnode 0x%" PRIx64
Packit Service 54dbc3
		", port number %u and\n\t\t\t\tnode 0x%" PRIx64
Packit Service 54dbc3
		", port number %u\n",
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_node)), port_num,
Packit Service 54dbc3
		cl_ntoh64(p_ni_context->node_guid), p_ni_context->port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	if (sm->ucast_mgr.cache_valid)
Packit Service 54dbc3
		osm_ucast_cache_check_new_link(&sm->ucast_mgr, p_node, port_num,
Packit Service 54dbc3
					       p_neighbor_node,
Packit Service 54dbc3
					       p_ni_context->port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
	p_remote_physp = osm_node_get_physp_ptr(p_neighbor_node,
Packit Service 54dbc3
						p_ni_context->port_num);
Packit Service 54dbc3
	if (!p_physp || !p_remote_physp)
Packit Service 54dbc3
		goto _exit;
Packit Service 54dbc3
Packit Service 54dbc3
	osm_node_link(p_node, port_num, p_neighbor_node, p_ni_context->port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_db_neighbor_set(sm->p_subn->p_neighbor,
Packit Service 54dbc3
			    cl_ntoh64(osm_physp_get_port_guid(p_physp)),
Packit Service 54dbc3
			    port_num,
Packit Service 54dbc3
			    cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
Packit Service 54dbc3
			    p_ni_context->port_num);
Packit Service 54dbc3
	osm_db_neighbor_set(sm->p_subn->p_neighbor,
Packit Service 54dbc3
			    cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
Packit Service 54dbc3
			    p_ni_context->port_num,
Packit Service 54dbc3
			    cl_ntoh64(osm_physp_get_port_guid(p_physp)),
Packit Service 54dbc3
			    port_num);
Packit Service 54dbc3
Packit Service 54dbc3
_exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ni_rcv_get_port_info(IN osm_sm_t * sm, IN osm_node_t * node,
Packit Service 54dbc3
				 IN const osm_madw_t * madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_physp_t *physp;
Packit Service 54dbc3
	ib_node_info_t *ni;
Packit Service 54dbc3
	unsigned port;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	int mlnx_epi_supported = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	ni = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(madw));
Packit Service 54dbc3
Packit Service 54dbc3
	port = ib_node_info_get_local_port_num(ni);
Packit Service 54dbc3
Packit Service 54dbc3
	if (sm->p_subn->opt.fdr10)
Packit Service 54dbc3
		mlnx_epi_supported = is_mlnx_ext_port_info_supported(
Packit Service 54dbc3
						ib_node_info_get_vendor_id(ni),
Packit Service 54dbc3
						ni->device_id);
Packit Service 54dbc3
Packit Service 54dbc3
	physp = osm_node_get_physp_ptr(node, port);
Packit Service 54dbc3
	if (!physp) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1E: "
Packit Service 54dbc3
			"Failed to find physp for port %d of Node GUID 0x%"
Packit Service 54dbc3
			PRIx64 "\n", port,
Packit Service 54dbc3
			cl_ntoh64(osm_node_get_node_guid(node)));
Packit Service 54dbc3
		return;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	context.pi_context.node_guid = osm_node_get_node_guid(node);
Packit Service 54dbc3
	context.pi_context.port_guid = osm_physp_get_port_guid(physp);
Packit Service 54dbc3
	context.pi_context.set_method = FALSE;
Packit Service 54dbc3
	context.pi_context.light_sweep = FALSE;
Packit Service 54dbc3
	context.pi_context.active_transition = FALSE;
Packit Service 54dbc3
	context.pi_context.client_rereg = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp),
Packit Service 54dbc3
			     IB_MAD_ATTR_PORT_INFO, cl_hton32(port),
Packit Service 54dbc3
			     TRUE, 0, 0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD02: "
Packit Service 54dbc3
			"Failure initiating PortInfo request (%s)\n",
Packit Service 54dbc3
			ib_get_err_str(status));
Packit Service 54dbc3
	if (mlnx_epi_supported) {
Packit Service 54dbc3
		status = osm_req_get(sm,
Packit Service 54dbc3
				     osm_physp_get_dr_path_ptr(physp),
Packit Service 54dbc3
				     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
Packit Service 54dbc3
				     cl_hton32(port),
Packit Service 54dbc3
				     TRUE, 0, 0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
		if (status != IB_SUCCESS)
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0B: "
Packit Service 54dbc3
				"Failure initiating MLNX ExtPortInfo request (%s)\n",
Packit Service 54dbc3
				ib_get_err_str(status));
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t * p_physp)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	context.nd_context.node_guid =
Packit Service 54dbc3
	    osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp));
Packit Service 54dbc3
Packit Service 54dbc3
	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
			     IB_MAD_ATTR_NODE_DESC, 0, TRUE, 0,
Packit Service 54dbc3
			     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D03: "
Packit Service 54dbc3
			"Failure initiating NodeDescription request (%s)\n",
Packit Service 54dbc3
			ib_get_err_str(status));
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_get_node_desc(IN osm_sm_t * sm, IN osm_node_t * p_node,
Packit Service 54dbc3
				 IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_node_info_t *p_ni;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
	osm_physp_t *p_physp = NULL;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
	port_num = ib_node_info_get_local_port_num(p_ni);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Request PortInfo & NodeDescription attributes for the port
Packit Service 54dbc3
	   that responded to the NodeInfo attribute.
Packit Service 54dbc3
	   Because this is a channel adapter or router, we are
Packit Service 54dbc3
	   not allowed to request PortInfo for the other ports.
Packit Service 54dbc3
	   Set the context union properly, so the recipient
Packit Service 54dbc3
	   knows which node & port are relevant.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
	if (!p_physp) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1F: "
Packit Service 54dbc3
			"Failed to find physp for port %d of Node GUID 0x%"
Packit Service 54dbc3
			PRIx64 "\n", port_num,
Packit Service 54dbc3
			cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
		return;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	osm_req_get_node_desc(sm, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_new_ca_or_router(IN osm_sm_t * sm,
Packit Service 54dbc3
					    IN osm_node_t * p_node,
Packit Service 54dbc3
					    IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	ni_rcv_get_port_info(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   A node guid of 0 is the corner case that indicates
Packit Service 54dbc3
	   we discovered our own node.  Initialize the subnet
Packit Service 54dbc3
	   object with the SM's own port guid.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0)
Packit Service 54dbc3
		sm->p_subn->sm_port_guid = p_node->node_info.port_guid;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_existing_ca_or_router(IN osm_sm_t * sm,
Packit Service 54dbc3
						 IN osm_node_t * p_node,
Packit Service 54dbc3
						 IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_node_info_t *p_ni;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	osm_port_t *p_port_check;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
	osm_dr_path_t *p_dr_path;
Packit Service 54dbc3
	osm_alias_guid_t *p_alias_guid, *p_alias_guid_check;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
	port_num = ib_node_info_get_local_port_num(p_ni);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Determine if we have encountered this node through a
Packit Service 54dbc3
	   previously undiscovered port.  If so, build the new
Packit Service 54dbc3
	   port object.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_port = osm_get_port_by_guid(sm->p_subn, p_ni->port_guid);
Packit Service 54dbc3
	if (!p_port) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Creating new port object with GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
Packit Service 54dbc3
		osm_node_init_physp(p_node, port_num, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
		p_port = osm_port_new(p_ni, p_node);
Packit Service 54dbc3
		if (PF(p_port == NULL)) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D04: "
Packit Service 54dbc3
				"Unable to create new port object\n");
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Add the new port object to the database.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		p_port_check =
Packit Service 54dbc3
		    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
Packit Service 54dbc3
						  p_ni->port_guid,
Packit Service 54dbc3
						  &p_port->map_item);
Packit Service 54dbc3
		if (PF(p_port_check != p_port)) {
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			   We should never be here!
Packit Service 54dbc3
			   Somehow, this port GUID already exists in the table.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D12: "
Packit Service 54dbc3
				"Port 0x%" PRIx64 " already in the database!\n",
Packit Service 54dbc3
				cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
Packit Service 54dbc3
			osm_port_delete(&p_port);
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		p_alias_guid = osm_alias_guid_new(p_ni->port_guid,
Packit Service 54dbc3
						  p_port);
Packit Service 54dbc3
		if (PF(!p_alias_guid)) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D11: "
Packit Service 54dbc3
				"alias guid memory allocation failed"
Packit Service 54dbc3
				" for port GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
				cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
			goto alias_done;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* insert into alias guid table */
Packit Service 54dbc3
		p_alias_guid_check =
Packit Service 54dbc3
			(osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl,
Packit Service 54dbc3
							    p_alias_guid->alias_guid,
Packit Service 54dbc3
							    &p_alias_guid->map_item);
Packit Service 54dbc3
		if (p_alias_guid_check != p_alias_guid) {
Packit Service 54dbc3
			/* alias GUID is a duplicate */
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D13: "
Packit Service 54dbc3
				"Duplicate alias port GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
				cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
			osm_alias_guid_delete(&p_alias_guid);
Packit Service 54dbc3
			osm_port_delete(&p_port);
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
alias_done:
Packit Service 54dbc3
		/* If we are a master, then this means the port is new on the subnet.
Packit Service 54dbc3
		   Mark it as new - need to send trap 64 for these ports.
Packit Service 54dbc3
		   The condition that we are master is true, since if we are in discovering
Packit Service 54dbc3
		   state (meaning we woke up from standby or we are just initializing),
Packit Service 54dbc3
		   then these ports may be new to us, but are not new on the subnet.
Packit Service 54dbc3
		   If we are master, then the subnet as we know it is the updated one,
Packit Service 54dbc3
		   and any new ports we encounter should cause trap 64. C14-72.1.1 */
Packit Service 54dbc3
		if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
Packit Service 54dbc3
			p_port->is_new = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		osm_physp_t *p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
Packit Service 54dbc3
		if (PF(p_physp == NULL)) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1C: "
Packit Service 54dbc3
				"No physical port found for node GUID 0x%"
Packit Service 54dbc3
				PRIx64 " port %u. Might be duplicate port GUID\n",
Packit Service 54dbc3
				cl_ntoh64(p_node->node_info.node_guid),
Packit Service 54dbc3
				port_num);
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Update the DR Path to the port,
Packit Service 54dbc3
		   in case the old one is no longer available.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
		osm_dr_path_init(p_dr_path, p_smp->hop_count,
Packit Service 54dbc3
				 p_smp->initial_path);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	ni_rcv_get_port_info(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ni_rcv_process_switch(IN osm_sm_t * sm, IN osm_node_t * p_node,
Packit Service 54dbc3
				  IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_dr_path_t *path;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, 0);
Packit Service 54dbc3
	/* update DR path of already initialized switch port 0 */
Packit Service 54dbc3
	path = osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
	osm_dr_path_init(path, p_smp->hop_count, p_smp->initial_path);
Packit Service 54dbc3
Packit Service 54dbc3
	context.si_context.node_guid = osm_node_get_node_guid(p_node);
Packit Service 54dbc3
	context.si_context.set_method = FALSE;
Packit Service 54dbc3
	context.si_context.light_sweep = FALSE;
Packit Service 54dbc3
	context.si_context.lft_top_change = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Request a SwitchInfo attribute */
Packit Service 54dbc3
	status = osm_req_get(sm, path, IB_MAD_ATTR_SWITCH_INFO, 0, TRUE, 0,
Packit Service 54dbc3
			     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		/* continue despite error */
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D06: "
Packit Service 54dbc3
			"Failure initiating SwitchInfo request (%s)\n",
Packit Service 54dbc3
			ib_get_err_str(status));
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_existing_switch(IN osm_sm_t * sm,
Packit Service 54dbc3
					   IN osm_node_t * p_node,
Packit Service 54dbc3
					   IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   If this switch has already been probed during this sweep,
Packit Service 54dbc3
	   then don't bother reprobing it.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_node->discovery_count == 1)
Packit Service 54dbc3
		ni_rcv_process_switch(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_new_switch(IN osm_sm_t * sm, IN osm_node_t * p_node,
Packit Service 54dbc3
				      IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	ni_rcv_process_switch(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   A node guid of 0 is the corner case that indicates
Packit Service 54dbc3
	   we discovered our own node.  Initialize the subnet
Packit Service 54dbc3
	   object with the SM's own port guid.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0)
Packit Service 54dbc3
		sm->p_subn->sm_port_guid = p_node->node_info.port_guid;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must NOT be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_new(IN osm_sm_t * sm, IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
	osm_node_t *p_node_check;
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	osm_port_t *p_port_check;
Packit Service 54dbc3
	osm_router_t *p_rtr = NULL;
Packit Service 54dbc3
	osm_router_t *p_rtr_check;
Packit Service 54dbc3
	cl_qmap_t *p_rtr_guid_tbl;
Packit Service 54dbc3
	ib_node_info_t *p_ni;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	osm_ni_context_t *p_ni_context;
Packit Service 54dbc3
	osm_alias_guid_t *p_alias_guid, *p_alias_guid_check;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
	p_ni_context = osm_madw_get_ni_context_ptr(p_madw);
Packit Service 54dbc3
	port_num = ib_node_info_get_local_port_num(p_ni);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
		"Discovered new %s node,"
Packit Service 54dbc3
		"\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n",
Packit Service 54dbc3
		ib_get_node_type_str(p_ni->node_type),
Packit Service 54dbc3
		cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id));
Packit Service 54dbc3
Packit Service 54dbc3
	if (PF(port_num > p_ni->num_ports)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0A: "
Packit Service 54dbc3
			"New %s node GUID 0x%" PRIx64 "is non-compliant and "
Packit Service 54dbc3
			"is being ignored since the "
Packit Service 54dbc3
			"local port num %u > num ports %u\n",
Packit Service 54dbc3
			ib_get_node_type_str(p_ni->node_type),
Packit Service 54dbc3
			cl_ntoh64(p_ni->node_guid), port_num,
Packit Service 54dbc3
			p_ni->num_ports);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_node = osm_node_new(p_madw);
Packit Service 54dbc3
	if (PF(p_node == NULL)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D07: "
Packit Service 54dbc3
			"Unable to create new node object\n");
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Create a new port object to represent this node's physical
Packit Service 54dbc3
	   ports in the port table.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_port = osm_port_new(p_ni, p_node);
Packit Service 54dbc3
	if (PF(p_port == NULL)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D14: "
Packit Service 54dbc3
			"Unable to create new port object\n");
Packit Service 54dbc3
		osm_node_delete(&p_node);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Add the new port object to the database.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_port_check =
Packit Service 54dbc3
	    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
Packit Service 54dbc3
					  p_ni->port_guid, &p_port->map_item);
Packit Service 54dbc3
	if (PF(p_port_check != p_port)) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   We should never be here!
Packit Service 54dbc3
		   Somehow, this port GUID already exists in the table.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D15: "
Packit Service 54dbc3
			"Duplicate Port GUID 0x%" PRIx64
Packit Service 54dbc3
			"! Found by the two directed routes:\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
		osm_dump_dr_path_v2(sm->p_log,
Packit Service 54dbc3
				    osm_physp_get_dr_path_ptr(p_port->p_physp),
Packit Service 54dbc3
				    FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
		osm_dump_dr_path_v2(sm->p_log,
Packit Service 54dbc3
				    osm_physp_get_dr_path_ptr(p_port_check->
Packit Service 54dbc3
							   p_physp),
Packit Service 54dbc3
				    FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
		osm_port_delete(&p_port);
Packit Service 54dbc3
		osm_node_delete(&p_node);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_alias_guid = osm_alias_guid_new(p_ni->port_guid,
Packit Service 54dbc3
					  p_port);
Packit Service 54dbc3
	if (PF(!p_alias_guid)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D18: "
Packit Service 54dbc3
			"alias guid memory allocation failed"
Packit Service 54dbc3
			" for port GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
		goto alias_done2;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* insert into alias guid table */
Packit Service 54dbc3
	p_alias_guid_check =
Packit Service 54dbc3
		(osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl,
Packit Service 54dbc3
						    p_alias_guid->alias_guid,
Packit Service 54dbc3
						    &p_alias_guid->map_item);
Packit Service 54dbc3
	if (p_alias_guid_check != p_alias_guid) {
Packit Service 54dbc3
		/* alias GUID is a duplicate */
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D19: "
Packit Service 54dbc3
			"Duplicate alias port GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
		osm_alias_guid_delete(&p_alias_guid);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
alias_done2:
Packit Service 54dbc3
	/* If we are a master, then this means the port is new on the subnet.
Packit Service 54dbc3
	   Mark it as new - need to send trap 64 on these ports.
Packit Service 54dbc3
	   The condition that we are master is true, since if we are in discovering
Packit Service 54dbc3
	   state (meaning we woke up from standby or we are just initializing),
Packit Service 54dbc3
	   then these ports may be new to us, but are not new on the subnet.
Packit Service 54dbc3
	   If we are master, then the subnet as we know it is the updated one,
Packit Service 54dbc3
	   and any new ports we encounter should cause trap 64. C14-72.1.1 */
Packit Service 54dbc3
	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
Packit Service 54dbc3
		p_port->is_new = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	/* If there were RouterInfo or other router attribute,
Packit Service 54dbc3
	   this would be elsewhere */
Packit Service 54dbc3
	if (p_ni->node_type == IB_NODE_TYPE_ROUTER) {
Packit Service 54dbc3
		if (PF((p_rtr = osm_router_new(p_port)) == NULL))
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1A: "
Packit Service 54dbc3
				"Unable to create new router object\n");
Packit Service 54dbc3
		else {
Packit Service 54dbc3
			p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl;
Packit Service 54dbc3
			p_rtr_check =
Packit Service 54dbc3
			    (osm_router_t *) cl_qmap_insert(p_rtr_guid_tbl,
Packit Service 54dbc3
							    p_ni->port_guid,
Packit Service 54dbc3
							    &p_rtr->map_item);
Packit Service 54dbc3
			if (PF(p_rtr_check != p_rtr))
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1B: "
Packit Service 54dbc3
					"Unable to add port GUID:0x%016" PRIx64
Packit Service 54dbc3
					" to router table\n",
Packit Service 54dbc3
					cl_ntoh64(p_ni->port_guid));
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_node_check =
Packit Service 54dbc3
	    (osm_node_t *) cl_qmap_insert(&sm->p_subn->node_guid_tbl,
Packit Service 54dbc3
					  p_ni->node_guid, &p_node->map_item);
Packit Service 54dbc3
	if (PF(p_node_check != p_node)) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   This node must have been inserted by another thread.
Packit Service 54dbc3
		   This is unexpected, but is not an error.
Packit Service 54dbc3
		   We can simply clean-up, since the other thread will
Packit Service 54dbc3
		   see this processing through to completion.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Discovery race detected at node 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->node_guid));
Packit Service 54dbc3
		osm_node_delete(&p_node);
Packit Service 54dbc3
		p_node = p_node_check;
Packit Service 54dbc3
		ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
Packit Service 54dbc3
Packit Service 54dbc3
	p_node->discovery_count++;
Packit Service 54dbc3
	ni_rcv_get_node_desc(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	switch (p_ni->node_type) {
Packit Service 54dbc3
	case IB_NODE_TYPE_CA:
Packit Service 54dbc3
	case IB_NODE_TYPE_ROUTER:
Packit Service 54dbc3
		ni_rcv_process_new_ca_or_router(sm, p_node, p_madw);
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	case IB_NODE_TYPE_SWITCH:
Packit Service 54dbc3
		ni_rcv_process_new_switch(sm, p_node, p_madw);
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	default:
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: "
Packit Service 54dbc3
			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ni_rcv_process_existing(IN osm_sm_t * sm, IN osm_node_t * p_node,
Packit Service 54dbc3
				    IN const osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_node_info_t *p_ni;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	osm_ni_context_t *p_ni_context;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
	p_ni_context = osm_madw_get_ni_context_ptr(p_madw);
Packit Service 54dbc3
	port_num = ib_node_info_get_local_port_num(p_ni);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
		"Rediscovered %s node 0x%" PRIx64 " TID 0x%" PRIx64
Packit Service 54dbc3
		", discovered %u times already\n",
Packit Service 54dbc3
		ib_get_node_type_str(p_ni->node_type),
Packit Service 54dbc3
		cl_ntoh64(p_ni->node_guid),
Packit Service 54dbc3
		cl_ntoh64(p_smp->trans_id), p_node->discovery_count);
Packit Service 54dbc3
Packit Service 54dbc3
	if (PF(port_num > p_ni->num_ports)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0C: "
Packit Service 54dbc3
			"Existing %s node GUID 0x%" PRIx64 "is non-compliant "
Packit Service 54dbc3
			"and is being ignored since the "
Packit Service 54dbc3
			"local port num %u > num ports %u\n",
Packit Service 54dbc3
			ib_get_node_type_str(p_ni->node_type),
Packit Service 54dbc3
			cl_ntoh64(p_ni->node_guid), port_num,
Packit Service 54dbc3
			p_ni->num_ports);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   If we haven't already encountered this existing node
Packit Service 54dbc3
	   on this particular sweep, then process further.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_node->discovery_count++;
Packit Service 54dbc3
Packit Service 54dbc3
	switch (p_ni->node_type) {
Packit Service 54dbc3
	case IB_NODE_TYPE_CA:
Packit Service 54dbc3
	case IB_NODE_TYPE_ROUTER:
Packit Service 54dbc3
		ni_rcv_process_existing_ca_or_router(sm, p_node, p_madw);
Packit Service 54dbc3
		break;
Packit Service 54dbc3
Packit Service 54dbc3
	case IB_NODE_TYPE_SWITCH:
Packit Service 54dbc3
		ni_rcv_process_existing_switch(sm, p_node, p_madw);
Packit Service 54dbc3
		break;
Packit Service 54dbc3
Packit Service 54dbc3
	default:
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D09: "
Packit Service 54dbc3
			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if ( p_ni->sys_guid != p_node->node_info.sys_guid) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Updated SysImageGUID: 0x%"
Packit Service 54dbc3
			PRIx64 " for node 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(p_ni->sys_guid),
Packit Service 54dbc3
			cl_ntoh64(p_ni->node_guid));
Packit Service 54dbc3
	}
Packit Service 54dbc3
	ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
Packit Service 54dbc3
	p_node->node_info = *p_ni;
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_ni_rcv_process(IN void *context, IN void *data)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_sm_t *sm = context;
Packit Service 54dbc3
	osm_madw_t *p_madw = data;
Packit Service 54dbc3
	ib_node_info_t *p_ni;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(sm);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_NODE_INFO);
Packit Service 54dbc3
Packit Service 54dbc3
	if (PF(p_ni->node_guid == 0)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: "
Packit Service 54dbc3
			"Got Zero Node GUID! Found on the directed route:\n");
Packit Service 54dbc3
		osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (PF(p_ni->port_guid == 0)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D17: "
Packit Service 54dbc3
			"Got Zero Port GUID! Found on the directed route:\n");
Packit Service 54dbc3
		osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (ib_smp_get_status(p_smp)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"MAD status 0x%x received\n",
Packit Service 54dbc3
			cl_ntoh16(ib_smp_get_status(p_smp)));
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Determine if this node has already been discovered,
Packit Service 54dbc3
	   and process accordingly.
Packit Service 54dbc3
	   During processing of this node, hold the shared lock.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
Packit Service 54dbc3
	p_node = osm_get_node_by_guid(sm->p_subn, p_ni->node_guid);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_dump_node_info_v2(sm->p_log, p_ni, FILE_ID, OSM_LOG_DEBUG);
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p_node)
Packit Service 54dbc3
		ni_rcv_process_new(sm, p_madw);
Packit Service 54dbc3
	else
Packit Service 54dbc3
		ni_rcv_process_existing(sm, p_node, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_RELEASE(sm->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}