Blame opensm/osm_ucast_mgr.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
 *
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_ucast_mgr_t.
Packit Service 54dbc3
 * This file implements the Unicast Manager object.
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 <stdio.h>
Packit Service 54dbc3
#include <stdlib.h>
Packit Service 54dbc3
#include <string.h>
Packit Service 54dbc3
#include <ctype.h>
Packit Service 54dbc3
#include <iba/ib_types.h>
Packit Service 54dbc3
#include <complib/cl_qmap.h>
Packit Service 54dbc3
#include <complib/cl_debug.h>
Packit Service 54dbc3
#include <complib/cl_qlist.h>
Packit Service 54dbc3
#include <opensm/osm_file_ids.h>
Packit Service 54dbc3
#define FILE_ID OSM_FILE_UCAST_MGR_C
Packit Service 54dbc3
#include <opensm/osm_ucast_mgr.h>
Packit Service 54dbc3
#include <opensm/osm_sm.h>
Packit Service 54dbc3
#include <opensm/osm_log.h>
Packit Service 54dbc3
#include <opensm/osm_node.h>
Packit Service 54dbc3
#include <opensm/osm_switch.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
Packit Service 54dbc3
void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	memset(p_mgr, 0, sizeof(*p_mgr));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_mgr->cache_valid)
Packit Service 54dbc3
		osm_ucast_cache_invalidate(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
ib_api_status_t osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr, IN osm_sm_t * sm)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_ucast_mgr_construct(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	p_mgr->sm = sm;
Packit Service 54dbc3
	p_mgr->p_log = sm->p_log;
Packit Service 54dbc3
	p_mgr->p_subn = sm->p_subn;
Packit Service 54dbc3
	p_mgr->p_lock = sm->p_lock;
Packit Service 54dbc3
Packit Service 54dbc3
	if (sm->p_subn->opt.use_ucast_cache)
Packit Service 54dbc3
		cl_qmap_init(&p_mgr->cache_sw_tbl);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return status;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 Add each switch's own and neighbor LIDs to its LID matrix
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void ucast_mgr_process_hop_0_1(IN cl_map_item_t * p_map_item,
Packit Service 54dbc3
				      IN void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	osm_node_t *p_remote_node;
Packit Service 54dbc3
	uint16_t lid, remote_lid;
Packit Service 54dbc3
	uint8_t i;
Packit Service 54dbc3
Packit Service 54dbc3
	lid = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
Packit Service 54dbc3
	osm_switch_set_hops(p_sw, lid, 0, 0);
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 1; i < p_sw->num_ports; i++) {
Packit Service 54dbc3
		osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, i);
Packit Service 54dbc3
		p_remote_node = (p && p->p_remote_physp) ?
Packit Service 54dbc3
		    p->p_remote_physp->p_node : NULL;
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_remote_node && p_remote_node->sw &&
Packit Service 54dbc3
		    p_remote_node != p_sw->p_node) {
Packit Service 54dbc3
			remote_lid = osm_node_get_base_lid(p_remote_node, 0);
Packit Service 54dbc3
			remote_lid = cl_ntoh16(remote_lid);
Packit Service 54dbc3
			osm_switch_set_hops(p_sw, remote_lid, i, p->hop_wf);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * p_mgr,
Packit Service 54dbc3
				       IN osm_switch_t * p_this_sw,
Packit Service 54dbc3
				       IN osm_switch_t * p_remote_sw,
Packit Service 54dbc3
				       IN uint8_t port_num,
Packit Service 54dbc3
				       IN uint8_t remote_port_num)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t *p_sw;
Packit Service 54dbc3
	cl_map_item_t *item;
Packit Service 54dbc3
	uint16_t lid_ho;
Packit Service 54dbc3
	uint16_t hops;
Packit Service 54dbc3
	osm_physp_t *p;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Node 0x%" PRIx64 ", remote node 0x%" PRIx64
Packit Service 54dbc3
		", port %u, remote port %u\n",
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
Packit Service 54dbc3
		port_num, remote_port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	p = osm_node_get_physp_ptr(p_this_sw->p_node, port_num);
Packit Service 54dbc3
Packit Service 54dbc3
	for (item = cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
Packit Service 54dbc3
	     item != cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl);
Packit Service 54dbc3
	     item = cl_qmap_next(item)) {
Packit Service 54dbc3
		p_sw = (osm_switch_t *) item;
Packit Service 54dbc3
		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
Packit Service 54dbc3
		hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
Packit Service 54dbc3
		if (hops == OSM_NO_PATH)
Packit Service 54dbc3
			continue;
Packit Service 54dbc3
		hops += p->hop_wf;
Packit Service 54dbc3
		if (hops <
Packit Service 54dbc3
		    osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
Packit Service 54dbc3
			if (osm_switch_set_hops
Packit Service 54dbc3
			    (p_this_sw, lid_ho, port_num, (uint8_t) hops) != 0)
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A03: "
Packit Service 54dbc3
					"cannot set hops for lid %u at switch 0x%"
Packit Service 54dbc3
					PRIx64 "\n", lid_ho,
Packit Service 54dbc3
					cl_ntoh64(osm_node_get_node_guid
Packit Service 54dbc3
						  (p_this_sw->p_node)));
Packit Service 54dbc3
			p_mgr->some_hop_count_set = TRUE;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static struct osm_remote_node *find_and_add_remote_sys(osm_switch_t * sw,
Packit Service 54dbc3
						       uint8_t port,
Packit Service 54dbc3
						       boolean_t dor, struct
Packit Service 54dbc3
						       osm_remote_guids_count
Packit Service 54dbc3
						       *r)
Packit Service 54dbc3
{
Packit Service 54dbc3
	unsigned i;
Packit Service 54dbc3
	osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
Packit Service 54dbc3
	osm_node_t *node = p->p_remote_physp->p_node;
Packit Service 54dbc3
	uint8_t rem_port = osm_physp_get_port_num(p->p_remote_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 0; i < r->count; i++)
Packit Service 54dbc3
		if (r->guids[i].node == node)
Packit Service 54dbc3
			if (!dor || (r->guids[i].port == rem_port))
Packit Service 54dbc3
				return &r->guids[i];
Packit Service 54dbc3
Packit Service 54dbc3
	r->guids[i].node = node;
Packit Service 54dbc3
	r->guids[i].forwarded_to = 0;
Packit Service 54dbc3
	r->guids[i].port = rem_port;
Packit Service 54dbc3
	r->count++;
Packit Service 54dbc3
	return &r->guids[i];
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr,
Packit Service 54dbc3
				   IN osm_switch_t * p_sw,
Packit Service 54dbc3
				   IN osm_port_t * p_port,
Packit Service 54dbc3
				   IN unsigned lid_offset)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint16_t min_lid_ho;
Packit Service 54dbc3
	uint16_t max_lid_ho;
Packit Service 54dbc3
	uint16_t lid_ho;
Packit Service 54dbc3
	uint8_t port;
Packit Service 54dbc3
	boolean_t is_ignored_by_port_prof;
Packit Service 54dbc3
	ib_net64_t node_guid;
Packit Service 54dbc3
	unsigned start_from = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
	/* If the lids are zero - then there was some problem with
Packit Service 54dbc3
	 * the initialization. Don't handle this port. */
Packit Service 54dbc3
	if (min_lid_ho == 0 || max_lid_ho == 0) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
Packit Service 54dbc3
			"Port 0x%" PRIx64 " (%s port %d) has LID 0. An "
Packit Service 54dbc3
			"initialization error occurred. Ignoring port\n",
Packit Service 54dbc3
			cl_ntoh64(osm_port_get_guid(p_port)),
Packit Service 54dbc3
			p_port->p_node->print_desc,
Packit Service 54dbc3
			p_port->p_physp->port_num);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	lid_ho = min_lid_ho + lid_offset;
Packit Service 54dbc3
Packit Service 54dbc3
	if (lid_ho > max_lid_ho)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
	if (lid_offset && !p_mgr->is_dor)
Packit Service 54dbc3
		/* ignore potential overflow - it is handled in osm_switch.c */
Packit Service 54dbc3
		start_from =
Packit Service 54dbc3
		    osm_switch_get_port_by_lid(p_sw, lid_ho - 1, OSM_NEW_LFT) + 1;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Processing port 0x%" PRIx64
Packit Service 54dbc3
		" (\'%s\' port %u), LID %u [%u,%u]\n",
Packit Service 54dbc3
		cl_ntoh64(osm_port_get_guid(p_port)),
Packit Service 54dbc3
		p_port->p_node->print_desc, p_port->p_physp->port_num, lid_ho,
Packit Service 54dbc3
		min_lid_ho, max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
	/* TODO - This should be runtime error, not a CL_ASSERT() */
Packit Service 54dbc3
	CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO);
Packit Service 54dbc3
Packit Service 54dbc3
	node_guid = osm_node_get_node_guid(p_sw->p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   The lid matrix contains the number of hops to each
Packit Service 54dbc3
	   lid from each port.  From this information we determine
Packit Service 54dbc3
	   how best to distribute the LID range across the ports
Packit Service 54dbc3
	   that can reach those LIDs.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
Packit Service 54dbc3
					 p_mgr->p_subn->ignore_existing_lfts,
Packit Service 54dbc3
					 p_mgr->p_subn->opt.lmc,
Packit Service 54dbc3
					 p_mgr->is_dor,
Packit Service 54dbc3
					 p_mgr->p_subn->opt.port_shifting,
Packit Service 54dbc3
					 !lid_offset && p_port->use_scatter,
Packit Service 54dbc3
					 OSM_LFT);
Packit Service 54dbc3
Packit Service 54dbc3
	if (port == OSM_NO_PATH) {
Packit Service 54dbc3
		/* do not try to overwrite the ppro of non existing port ... */
Packit Service 54dbc3
		is_ignored_by_port_prof = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"No path to get to LID %u from switch 0x%" PRIx64 "\n",
Packit Service 54dbc3
			lid_ho, cl_ntoh64(node_guid));
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
Packit Service 54dbc3
		if (!p)
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Routing LID %u to port %u for switch 0x%" PRIx64 "\n",
Packit Service 54dbc3
			lid_ho, port, cl_ntoh64(node_guid));
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   we would like to optionally ignore this port in equalization
Packit Service 54dbc3
		   as in the case of the Mellanox Anafa Internal PCI TCA port
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		is_ignored_by_port_prof = p->is_prof_ignored;
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   We also would ignore this route if the target lid is of
Packit Service 54dbc3
		   a switch and the port_profile_switch_node is not TRUE
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
Packit Service 54dbc3
			is_ignored_by_port_prof |=
Packit Service 54dbc3
			    (osm_node_get_type(p_port->p_node) ==
Packit Service 54dbc3
			     IB_NODE_TYPE_SWITCH);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   We have selected the port for this LID.
Packit Service 54dbc3
	   Write it to the forwarding tables.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_sw->new_lft[lid_ho] = port;
Packit Service 54dbc3
	if (!is_ignored_by_port_prof) {
Packit Service 54dbc3
		struct osm_remote_node *rem_node_used;
Packit Service 54dbc3
		osm_switch_count_path(p_sw, port);
Packit Service 54dbc3
		if (port > 0 && p_port->priv &&
Packit Service 54dbc3
		    (rem_node_used = find_and_add_remote_sys(p_sw, port,
Packit Service 54dbc3
							     p_mgr->is_dor,
Packit Service 54dbc3
							     p_port->priv)))
Packit Service 54dbc3
			rem_node_used->forwarded_to++;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void alloc_ports_priv(osm_ucast_mgr_t * mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
Packit Service 54dbc3
	struct osm_remote_guids_count *r;
Packit Service 54dbc3
	osm_port_t *port;
Packit Service 54dbc3
	cl_map_item_t *item;
Packit Service 54dbc3
	unsigned lmc;
Packit Service 54dbc3
Packit Service 54dbc3
	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
Packit Service 54dbc3
	     item = cl_qmap_next(item)) {
Packit Service 54dbc3
		port = (osm_port_t *) item;
Packit Service 54dbc3
		lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
Packit Service 54dbc3
		r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
Packit Service 54dbc3
		if (!r) {
Packit Service 54dbc3
			OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
Packit Service 54dbc3
				"cannot allocate memory to track remote"
Packit Service 54dbc3
				" systems for lmc > 0\n");
Packit Service 54dbc3
			port->priv = NULL;
Packit Service 54dbc3
			continue;
Packit Service 54dbc3
		}
Packit Service 54dbc3
		memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
Packit Service 54dbc3
		port->priv = r;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void free_ports_priv(osm_ucast_mgr_t * mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
Packit Service 54dbc3
	osm_port_t *port;
Packit Service 54dbc3
	cl_map_item_t *item;
Packit Service 54dbc3
	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
Packit Service 54dbc3
	     item = cl_qmap_next(item)) {
Packit Service 54dbc3
		port = (osm_port_t *) item;
Packit Service 54dbc3
		if (port->priv) {
Packit Service 54dbc3
			free(port->priv);
Packit Service 54dbc3
			port->priv = NULL;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item,
Packit Service 54dbc3
				  IN void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *p_mgr = context;
Packit Service 54dbc3
	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	unsigned i, lids_per_port;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_sw && p_sw->p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Processing switch 0x%" PRIx64 "\n",
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
Packit Service 54dbc3
Packit Service 54dbc3
	/* Initialize LIDs in buffer to invalid port number. */
Packit Service 54dbc3
	memset(p_sw->new_lft, OSM_NO_PATH, p_sw->max_lid_ho + 1);
Packit Service 54dbc3
Packit Service 54dbc3
	alloc_ports_priv(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Iterate through every port setting LID routes for each
Packit Service 54dbc3
	   port based on base LID and LMC value.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
Packit Service 54dbc3
	for (i = 0; i < lids_per_port; i++) {
Packit Service 54dbc3
		cl_qlist_t *list = &p_mgr->port_order_list;
Packit Service 54dbc3
		cl_list_item_t *item;
Packit Service 54dbc3
		for (item = cl_qlist_head(list); item != cl_qlist_end(list);
Packit Service 54dbc3
		     item = cl_qlist_next(item)) {
Packit Service 54dbc3
			osm_port_t *port = cl_item_obj(item, port, list_item);
Packit Service 54dbc3
			ucast_mgr_process_port(p_mgr, p_sw, port, i);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	free_ports_priv(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_process_neighbors(IN cl_map_item_t * p_map_item,
Packit Service 54dbc3
					IN void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	osm_ucast_mgr_t * p_mgr = context;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
	osm_node_t *p_remote_node;
Packit Service 54dbc3
	uint32_t port_num;
Packit Service 54dbc3
	uint8_t remote_port_num;
Packit Service 54dbc3
	uint32_t num_ports;
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_node = p_sw->p_node;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_node);
Packit Service 54dbc3
	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Processing switch with GUID 0x%" PRIx64 "\n",
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_node)));
Packit Service 54dbc3
Packit Service 54dbc3
	num_ports = osm_node_get_num_physp(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Start with port 1 to skip the switch's management port.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	for (port_num = 1; port_num < num_ports; port_num++) {
Packit Service 54dbc3
		p_remote_node = osm_node_get_remote_node(p_node,
Packit Service 54dbc3
							 (uint8_t) port_num,
Packit Service 54dbc3
							 &remote_port_num);
Packit Service 54dbc3
		if (p_remote_node && p_remote_node->sw
Packit Service 54dbc3
		    && (p_remote_node != p_node)) {
Packit Service 54dbc3
			/* make sure the link is healthy. If it is not - don't
Packit Service 54dbc3
			   propagate through it. */
Packit Service 54dbc3
			p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
			if (!p_physp || !osm_link_is_healthy(p_physp))
Packit Service 54dbc3
				continue;
Packit Service 54dbc3
Packit Service 54dbc3
			ucast_mgr_process_neighbor(p_mgr, p_sw,
Packit Service 54dbc3
						   p_remote_node->sw,
Packit Service 54dbc3
						   (uint8_t) port_num,
Packit Service 54dbc3
						   remote_port_num);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int set_hop_wf(void *ctx, uint64_t guid, char *p)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *m = ctx;
Packit Service 54dbc3
	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
Packit Service 54dbc3
	osm_physp_t *physp;
Packit Service 54dbc3
	unsigned port, hop_wf;
Packit Service 54dbc3
	char *e;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!node || !node->sw) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"switch with guid 0x%016" PRIx64 " is not found\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p || !*p || !(port = strtoul(p, &e, 0)) || (p == e) ||
Packit Service 54dbc3
	    port >= node->sw->num_ports) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p = e + 1;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!*p || !(hop_wf = strtoul(p, &e, 0)) || p == e || hop_wf >= 0x100) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"bad hop weight factor specified for guid 0x%016" PRIx64
Packit Service 54dbc3
			"port %u\n", guid, port);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	physp = osm_node_get_physp_ptr(node, port);
Packit Service 54dbc3
	if (!physp)
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
Packit Service 54dbc3
	physp->hop_wf = hop_wf;
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void set_default_hop_wf(cl_map_item_t * p_map_item, void *ctx)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t *sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	int i;
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 1; i < sw->num_ports; i++) {
Packit Service 54dbc3
		osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
Packit Service 54dbc3
		if (p)
Packit Service 54dbc3
			p->hop_wf = 1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int set_search_ordering_ports(void *ctx, uint64_t guid, char *p)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_subn_t *p_subn = ctx;
Packit Service 54dbc3
	osm_node_t *node = osm_get_node_by_guid(p_subn, cl_hton64(guid));
Packit Service 54dbc3
	osm_switch_t *sw;
Packit Service 54dbc3
	uint8_t *search_ordering_ports = NULL;
Packit Service 54dbc3
	uint8_t port;
Packit Service 54dbc3
	unsigned int *ports = NULL;
Packit Service 54dbc3
	const int bpw = sizeof(*ports)*8;
Packit Service 54dbc3
	int words;
Packit Service 54dbc3
	int i = 1; /* port 0 maps to port 0 */
Packit Service 54dbc3
Packit Service 54dbc3
	if (!node || !(sw = node->sw)) {
Packit Service 54dbc3
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"switch with guid 0x%016" PRIx64 " is not found\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (sw->search_ordering_ports) {
Packit Service 54dbc3
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"switch with guid 0x%016" PRIx64 " already listed\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	search_ordering_ports = malloc(sizeof(*search_ordering_ports)*sw->num_ports);
Packit Service 54dbc3
	if (!search_ordering_ports) {
Packit Service 54dbc3
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"ERR 3A07: cannot allocate memory for search_ordering_ports\n");
Packit Service 54dbc3
		return -1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	memset(search_ordering_ports, 0, sizeof(*search_ordering_ports)*sw->num_ports);
Packit Service 54dbc3
Packit Service 54dbc3
	/* the ports array is for record keeping of which ports have
Packit Service 54dbc3
	 * been seen */
Packit Service 54dbc3
	words = (sw->num_ports + bpw - 1)/bpw;
Packit Service 54dbc3
	ports = malloc(words*sizeof(*ports));
Packit Service 54dbc3
	if (!ports) {
Packit Service 54dbc3
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"ERR 3A08: cannot allocate memory for ports\n");
Packit Service 54dbc3
		free(search_ordering_ports);
Packit Service 54dbc3
		return -1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	memset(ports, 0, words*sizeof(*ports));
Packit Service 54dbc3
Packit Service 54dbc3
	while ((*p != '\0') && (*p != '#')) {
Packit Service 54dbc3
		char *e;
Packit Service 54dbc3
Packit Service 54dbc3
		port = strtoul(p, &e, 0);
Packit Service 54dbc3
		if ((p == e) || (port == 0) || (port >= sw->num_ports) ||
Packit Service 54dbc3
		    !osm_node_get_physp_ptr(node, port)) {
Packit Service 54dbc3
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"bad port %d specified for guid 0x%016" PRIx64 "\n",
Packit Service 54dbc3
				port, guid);
Packit Service 54dbc3
			free(search_ordering_ports);
Packit Service 54dbc3
			free(ports);
Packit Service 54dbc3
			return 0;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		if (ports[port/bpw] & (1u << (port%bpw))) {
Packit Service 54dbc3
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"port %d already specified for guid 0x%016" PRIx64 "\n",
Packit Service 54dbc3
				port, guid);
Packit Service 54dbc3
			free(search_ordering_ports);
Packit Service 54dbc3
			free(ports);
Packit Service 54dbc3
			return 0;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		ports[port/bpw] |= (1u << (port%bpw));
Packit Service 54dbc3
		search_ordering_ports[i++] = port;
Packit Service 54dbc3
Packit Service 54dbc3
		p = e;
Packit Service 54dbc3
		while (isspace(*p)) {
Packit Service 54dbc3
			p++;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (i > 1) {
Packit Service 54dbc3
		for (port = 1; port < sw->num_ports; port++) {
Packit Service 54dbc3
			/* fill out the rest of the search_ordering_ports array
Packit Service 54dbc3
			 * in sequence using the remaining unspecified
Packit Service 54dbc3
			 * ports.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			if (!(ports[port/bpw] & (1u << (port%bpw)))) {
Packit Service 54dbc3
				search_ordering_ports[i++] = port;
Packit Service 54dbc3
			}
Packit Service 54dbc3
		}
Packit Service 54dbc3
		sw->search_ordering_ports = search_ordering_ports;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		free(search_ordering_ports);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	free(ports);
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint32_t i;
Packit Service 54dbc3
	uint32_t iteration_max;
Packit Service 54dbc3
	cl_qmap_t *p_sw_guid_tbl;
Packit Service 54dbc3
Packit Service 54dbc3
	p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
		"Starting switches' Min Hop Table Assignment\n");
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Set up the weighting factors for the routing.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	cl_qmap_apply_func(p_sw_guid_tbl, set_default_hop_wf, NULL);
Packit Service 54dbc3
	if (p_mgr->p_subn->opt.hop_weights_file) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Fetching hop weight factor file \'%s\'\n",
Packit Service 54dbc3
			p_mgr->p_subn->opt.hop_weights_file);
Packit Service 54dbc3
		if (parse_node_map(p_mgr->p_subn->opt.hop_weights_file,
Packit Service 54dbc3
				   set_hop_wf, p_mgr)) {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: "
Packit Service 54dbc3
				"cannot parse hop_weights_file \'%s\'\n",
Packit Service 54dbc3
				p_mgr->p_subn->opt.hop_weights_file);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Set the switch matrices for each switch's own port 0 LID(s)
Packit Service 54dbc3
	   then set the lid matrices for the each switch's leaf nodes.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	cl_qmap_apply_func(p_sw_guid_tbl, ucast_mgr_process_hop_0_1, p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Get the switch matrices for each switch's neighbors.
Packit Service 54dbc3
	   This process requires a number of iterations equal to
Packit Service 54dbc3
	   the number of switches in the subnet minus 1.
Packit Service 54dbc3
Packit Service 54dbc3
	   In each iteration, a switch learns the lid/port/hop
Packit Service 54dbc3
	   information (as contained by a switch's lid matrix) from
Packit Service 54dbc3
	   its immediate neighbors.  After each iteration, a switch
Packit Service 54dbc3
	   (and it's neighbors) know more routing information than
Packit Service 54dbc3
	   it did on the previous iteration.
Packit Service 54dbc3
	   Thus, by repeatedly absorbing the routing information of
Packit Service 54dbc3
	   neighbor switches, every switch eventually learns how to
Packit Service 54dbc3
	   route all LIDs on the subnet.
Packit Service 54dbc3
Packit Service 54dbc3
	   Note that there may not be any switches in the subnet if
Packit Service 54dbc3
	   we are in simple p2p configuration.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	iteration_max = cl_qmap_count(p_sw_guid_tbl);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   If there are switches in the subnet, iterate until the lid
Packit Service 54dbc3
	   matrix has been constructed.  Otherwise, just immediately
Packit Service 54dbc3
	   indicate we're done if no switches exist.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (iteration_max) {
Packit Service 54dbc3
		iteration_max--;
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   we need to find out when the propagation of
Packit Service 54dbc3
		   hop counts has relaxed. So this global variable
Packit Service 54dbc3
		   is preset to 0 on each iteration and if
Packit Service 54dbc3
		   if non of the switches was set will exit the
Packit Service 54dbc3
		   while loop
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		p_mgr->some_hop_count_set = TRUE;
Packit Service 54dbc3
		for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
Packit Service 54dbc3
		     i++) {
Packit Service 54dbc3
			p_mgr->some_hop_count_set = FALSE;
Packit Service 54dbc3
			cl_qmap_apply_func(p_sw_guid_tbl,
Packit Service 54dbc3
					   ucast_mgr_process_neighbors, p_mgr);
Packit Service 54dbc3
		}
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Min-hop propagated in %d steps\n", i);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t *p_sw;
Packit Service 54dbc3
	uint16_t lids;
Packit Service 54dbc3
Packit Service 54dbc3
	lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);
Packit Service 54dbc3
	lids = lids ? lids - 1 : 0;
Packit Service 54dbc3
Packit Service 54dbc3
	for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
Packit Service 54dbc3
	     p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl);
Packit Service 54dbc3
	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {
Packit Service 54dbc3
		if (osm_switch_prepare_path_rebuild(p_sw, lids)) {
Packit Service 54dbc3
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: "
Packit Service 54dbc3
				"cannot setup switch 0x%016" PRIx64 "\n",
Packit Service 54dbc3
				cl_ntoh64(osm_node_get_node_guid
Packit Service 54dbc3
					  (p_sw->p_node)));
Packit Service 54dbc3
			return -1;
Packit Service 54dbc3
		}
Packit Service 54dbc3
		if (p_sw->search_ordering_ports) {
Packit Service 54dbc3
			free(p_sw->search_ordering_ports);
Packit Service 54dbc3
			p_sw->search_ordering_ports = NULL;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_subn->opt.port_search_ordering_file) {
Packit Service 54dbc3
		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Fetching dimension ports file \'%s\'\n",
Packit Service 54dbc3
			p_subn->opt.port_search_ordering_file);
Packit Service 54dbc3
		if (parse_node_map(p_subn->opt.port_search_ordering_file,
Packit Service 54dbc3
				   set_search_ordering_ports, p_subn)) {
Packit Service 54dbc3
			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0F: "
Packit Service 54dbc3
				"cannot parse port_search_ordering_file \'%s\'\n",
Packit Service 54dbc3
				p_subn->opt.port_search_ordering_file);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *m = ctx;
Packit Service 54dbc3
	osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
Packit Service 54dbc3
Packit Service 54dbc3
	if (!port) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"port guid not found: 0x%016" PRIx64 "\n", guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (port->flag) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"port guid specified multiple times 0x%016" PRIx64 "\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
Packit Service 54dbc3
	port->flag = 1;
Packit Service 54dbc3
	port->use_scatter =  (m->p_subn->opt.guid_routing_order_no_scatter == TRUE) ? 0 : m->p_subn->opt.scatter_ports;
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void add_port_to_order_list(cl_map_item_t * p_map_item, void *ctx)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_port_t *port = (osm_port_t *) p_map_item;
Packit Service 54dbc3
	osm_ucast_mgr_t *m = ctx;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!port->flag) {
Packit Service 54dbc3
		port->use_scatter = m->p_subn->opt.scatter_ports;
Packit Service 54dbc3
		cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		port->flag = 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *m = ctx;
Packit Service 54dbc3
	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
Packit Service 54dbc3
	osm_physp_t *physp;
Packit Service 54dbc3
	unsigned port;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!node || !node->sw) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"switch with guid 0x%016" PRIx64 " is not found\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
Packit Service 54dbc3
	    port >= node->sw->num_ports) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	physp = osm_node_get_physp_ptr(node, port);
Packit Service 54dbc3
	if (!physp)
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
Packit Service 54dbc3
	physp->is_prof_ignored = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void clear_prof_ignore_flag(cl_map_item_t * p_map_item, void *ctx)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_switch_t *sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	int i;
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 1; i < sw->num_ports; i++) {
Packit Service 54dbc3
		osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
Packit Service 54dbc3
		if (p)
Packit Service 54dbc3
			p->is_prof_ignored = 0;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void add_sw_endports_to_order_list(osm_switch_t * sw,
Packit Service 54dbc3
					  osm_ucast_mgr_t * m)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_port_t *port;
Packit Service 54dbc3
	osm_physp_t *p;
Packit Service 54dbc3
	int i;
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 1; i < sw->num_ports; i++) {
Packit Service 54dbc3
		p = osm_node_get_physp_ptr(sw->p_node, i);
Packit Service 54dbc3
		if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) {
Packit Service 54dbc3
			port = osm_get_port_by_guid(m->p_subn,
Packit Service 54dbc3
						    p->p_remote_physp->
Packit Service 54dbc3
						    port_guid);
Packit Service 54dbc3
			if (!port || port->flag)
Packit Service 54dbc3
				continue;
Packit Service 54dbc3
			cl_qlist_insert_tail(&m->port_order_list,
Packit Service 54dbc3
					     &port->list_item);
Packit Service 54dbc3
			port->flag = 1;
Packit Service 54dbc3
			port->use_scatter = m->p_subn->opt.scatter_ports;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void sw_count_endport_links(osm_switch_t * sw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_physp_t *p;
Packit Service 54dbc3
	int i;
Packit Service 54dbc3
Packit Service 54dbc3
	sw->endport_links = 0;
Packit Service 54dbc3
	for (i = 1; i < sw->num_ports; i++) {
Packit Service 54dbc3
		p = osm_node_get_physp_ptr(sw->p_node, i);
Packit Service 54dbc3
		if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw)
Packit Service 54dbc3
			sw->endport_links++;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int compar_sw_load(const void *s1, const void *s2)
Packit Service 54dbc3
{
Packit Service 54dbc3
#define get_sw_endport_links(s) (*(osm_switch_t **)s)->endport_links
Packit Service 54dbc3
	return get_sw_endport_links(s2) - get_sw_endport_links(s1);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void sort_ports_by_switch_load(osm_ucast_mgr_t * m)
Packit Service 54dbc3
{
Packit Service 54dbc3
	int i, num = cl_qmap_count(&m->p_subn->sw_guid_tbl);
Packit Service 54dbc3
	void **s = malloc(num * sizeof(*s));
Packit Service 54dbc3
	if (!s) {
Packit Service 54dbc3
		OSM_LOG(m->p_log, OSM_LOG_ERROR, "ERR 3A0C: "
Packit Service 54dbc3
			"No memory, skip by switch load sorting.\n");
Packit Service 54dbc3
		return;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	s[0] = cl_qmap_head(&m->p_subn->sw_guid_tbl);
Packit Service 54dbc3
	for (i = 1; i < num; i++)
Packit Service 54dbc3
		s[i] = cl_qmap_next(s[i - 1]);
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 0; i < num; i++)
Packit Service 54dbc3
		sw_count_endport_links(s[i]);
Packit Service 54dbc3
Packit Service 54dbc3
	qsort(s, num, sizeof(*s), compar_sw_load);
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = 0; i < num; i++)
Packit Service 54dbc3
		add_sw_endports_to_order_list(s[i], m);
Packit Service 54dbc3
	free(s);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_mgr_build_lfts(osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qlist_init(&p_mgr->port_order_list);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_mgr->p_subn->opt.guid_routing_order_file) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Fetching guid routing order file \'%s\'\n",
Packit Service 54dbc3
			p_mgr->p_subn->opt.guid_routing_order_file);
Packit Service 54dbc3
Packit Service 54dbc3
		if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
Packit Service 54dbc3
				   add_guid_to_order_list, p_mgr))
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0D: "
Packit Service 54dbc3
				"cannot parse guid routing order file \'%s\'\n",
Packit Service 54dbc3
				p_mgr->p_subn->opt.guid_routing_order_file);
Packit Service 54dbc3
	}
Packit Service 54dbc3
	sort_ports_by_switch_load(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_mgr->p_subn->opt.port_prof_ignore_file) {
Packit Service 54dbc3
		cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
Packit Service 54dbc3
				   clear_prof_ignore_flag, NULL);
Packit Service 54dbc3
		if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
Packit Service 54dbc3
				   mark_ignored_port, p_mgr)) {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0E: "
Packit Service 54dbc3
				"cannot parse port prof ignore file \'%s\'\n",
Packit Service 54dbc3
				p_mgr->p_subn->opt.port_prof_ignore_file);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
Packit Service 54dbc3
			   add_port_to_order_list, p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_process_tbl,
Packit Service 54dbc3
			   p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qlist_remove_all(&p_mgr->port_order_list);
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item,
Packit Service 54dbc3
				  IN void *cxt)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *p_mgr = cxt;
Packit Service 54dbc3
	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
	osm_dr_path_t *p_path;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	ib_switch_info_t si;
Packit Service 54dbc3
	boolean_t set_swinfo_require = FALSE;
Packit Service 54dbc3
	uint16_t lin_top;
Packit Service 54dbc3
	uint8_t life_state;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_sw && p_sw->max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
	p_node = p_sw->p_node;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_mgr->max_lid < p_sw->max_lid_ho)
Packit Service 54dbc3
		p_mgr->max_lid = p_sw->max_lid_ho;
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, 0);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	p_path = osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Set the top of the unicast forwarding table.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	si = p_sw->switch_info;
Packit Service 54dbc3
	lin_top = cl_hton16(p_sw->max_lid_ho);
Packit Service 54dbc3
	if (lin_top != si.lin_top) {
Packit Service 54dbc3
		set_swinfo_require = TRUE;
Packit Service 54dbc3
		si.lin_top = lin_top;
Packit Service 54dbc3
		context.si_context.lft_top_change = TRUE;
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		context.si_context.lft_top_change = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	life_state = si.life_state;
Packit Service 54dbc3
	ib_switch_info_set_life_time(&si, p_mgr->p_subn->opt.packet_life_time);
Packit Service 54dbc3
Packit Service 54dbc3
	if (life_state != si.life_state)
Packit Service 54dbc3
		set_swinfo_require = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	if (set_swinfo_require) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Setting switch FT top to LID %u\n", p_sw->max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
		context.si_context.light_sweep = FALSE;
Packit Service 54dbc3
		context.si_context.node_guid = osm_node_get_node_guid(p_node);
Packit Service 54dbc3
		context.si_context.set_method = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
Packit Service 54dbc3
				     sizeof(si), IB_MAD_ATTR_SWITCH_INFO,
Packit Service 54dbc3
				     0, FALSE,
Packit Service 54dbc3
				     ib_port_info_get_m_key(&p_physp->port_info),
Packit Service 54dbc3
				     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
Packit Service 54dbc3
		if (status != IB_SUCCESS)
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
Packit Service 54dbc3
				"Sending SwitchInfo attribute failed (%s)\n",
Packit Service 54dbc3
				ib_get_err_str(status));
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr,
Packit Service 54dbc3
			 IN uint16_t block_id_ho)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_dr_path_t *p_path;
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Send linear forwarding table blocks to the switch
Packit Service 54dbc3
	   as long as the switch indicates it has blocks needing
Packit Service 54dbc3
	   configuration.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (!p_sw->new_lft) {
Packit Service 54dbc3
		/* any routing should provide the new_lft */
Packit Service 54dbc3
		CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
Packit Service 54dbc3
			  p_mgr->cache_valid && !p_sw->need_update);
Packit Service 54dbc3
		return -1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_sw->p_node, 0);
Packit Service 54dbc3
	if (!p_physp)
Packit Service 54dbc3
		return -1;
Packit Service 54dbc3
Packit Service 54dbc3
	p_path = osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	context.lft_context.node_guid = osm_node_get_node_guid(p_sw->p_node);
Packit Service 54dbc3
	context.lft_context.set_method = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p_sw->need_update && !p_mgr->p_subn->need_update &&
Packit Service 54dbc3
	    !memcmp(p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
Packit Service 54dbc3
		    p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE,
Packit Service 54dbc3
		    IB_SMP_DATA_SIZE))
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Zero the stored LFT block, so in case the MAD will end up
Packit Service 54dbc3
	 * with error, we will resend it in the next sweep.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	memset(p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, 0,
Packit Service 54dbc3
	       IB_SMP_DATA_SIZE);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Writing FT block %u to switch 0x%" PRIx64 "\n", block_id_ho,
Packit Service 54dbc3
		cl_ntoh64(context.lft_context.node_guid));
Packit Service 54dbc3
Packit Service 54dbc3
	status = osm_req_set(p_mgr->sm, p_path,
Packit Service 54dbc3
			     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
Packit Service 54dbc3
			     IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL,
Packit Service 54dbc3
			     cl_hton32(block_id_ho), FALSE,
Packit Service 54dbc3
			     ib_port_info_get_m_key(&p_physp->port_info),
Packit Service 54dbc3
			     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
Packit Service 54dbc3
	if (status != IB_SUCCESS) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A10: "
Packit Service 54dbc3
			"Sending linear fwd. tbl. block failed (%s)\n",
Packit Service 54dbc3
			ib_get_err_str(status));
Packit Service 54dbc3
		return -1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void ucast_mgr_pipeline_fwd_tbl(osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qmap_t *tbl;
Packit Service 54dbc3
	cl_map_item_t *item;
Packit Service 54dbc3
	unsigned i, max_block = p_mgr->max_lid / IB_SMP_DATA_SIZE + 1;
Packit Service 54dbc3
Packit Service 54dbc3
	tbl = &p_mgr->p_subn->sw_guid_tbl;
Packit Service 54dbc3
	for (i = 0; i < max_block; i++)
Packit Service 54dbc3
		for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl);
Packit Service 54dbc3
		     item = cl_qmap_next(item))
Packit Service 54dbc3
			set_lft_block((osm_switch_t *)item, p_mgr, i);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_ucast_mgr_set_fwd_tables(osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	p_mgr->max_lid = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_set_fwd_top,
Packit Service 54dbc3
			   p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	ucast_mgr_pipeline_fwd_tbl(p_mgr);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t * osm)
Packit Service 54dbc3
{
Packit Service 54dbc3
	int ret;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
		"building routing with \'%s\' routing algorithm...\n", r->name);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Set the before each lft build to keep the routes in place between sweeps */
Packit Service 54dbc3
	if (osm->subn.opt.scatter_ports)
Packit Service 54dbc3
		srandom(osm->subn.opt.scatter_ports);
Packit Service 54dbc3
Packit Service 54dbc3
	if (!r->build_lid_matrices ||
Packit Service 54dbc3
	    (ret = r->build_lid_matrices(r->context)) > 0)
Packit Service 54dbc3
		ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	if (ret < 0) {
Packit Service 54dbc3
		OSM_LOG(&osm->log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"%s: cannot build lid matrices\n", r->name);
Packit Service 54dbc3
		return ret;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (!r->ucast_build_fwd_tables ||
Packit Service 54dbc3
	    (ret = r->ucast_build_fwd_tables(r->context)) > 0)
Packit Service 54dbc3
		ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	if (ret < 0) {
Packit Service 54dbc3
		OSM_LOG(&osm->log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"%s: cannot build fwd tables\n", r->name);
Packit Service 54dbc3
		return ret;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	osm->routing_engine_used = r;
Packit Service 54dbc3
Packit Service 54dbc3
	osm_ucast_mgr_set_fwd_tables(&osm->sm.ucast_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_opensm_t *p_osm;
Packit Service 54dbc3
	struct osm_routing_engine *p_routing_eng;
Packit Service 54dbc3
	cl_qmap_t *p_sw_guid_tbl;
Packit Service 54dbc3
	int failed = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
Packit Service 54dbc3
	p_osm = p_mgr->p_subn->p_osm;
Packit Service 54dbc3
	p_routing_eng = p_osm->routing_engine_list;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   If there are no switches in the subnet, we are done.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (cl_qmap_count(p_sw_guid_tbl) == 0 ||
Packit Service 54dbc3
	    ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
	failed = -1;
Packit Service 54dbc3
	p_osm->routing_engine_used = NULL;
Packit Service 54dbc3
	while (p_routing_eng) {
Packit Service 54dbc3
		failed = ucast_mgr_route(p_routing_eng, p_osm);
Packit Service 54dbc3
		if (!failed)
Packit Service 54dbc3
			break;
Packit Service 54dbc3
		p_routing_eng = p_routing_eng->next;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p_osm->routing_engine_used &&
Packit Service 54dbc3
	    p_osm->no_fallback_routing_engine != TRUE) {
Packit Service 54dbc3
		/* If configured routing algorithm failed, use default MinHop */
Packit Service 54dbc3
		failed = ucast_mgr_route(p_osm->default_routing_engine, p_osm);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_osm->routing_engine_used) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
Packit Service 54dbc3
			"%s tables configured on all switches\n",
Packit Service 54dbc3
			osm_routing_engine_type_str(p_osm->
Packit Service 54dbc3
						    routing_engine_used->type));
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_mgr->p_subn->opt.use_ucast_cache)
Packit Service 54dbc3
			p_mgr->cache_valid = TRUE;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		p_mgr->p_subn->subnet_initialization_error = TRUE;
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"No routing engine able to successfully configure "
Packit Service 54dbc3
			" switch tables on current fabric\n");
Packit Service 54dbc3
	}
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	CL_PLOCK_RELEASE(p_mgr->p_lock);
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return failed;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_build_lid_matrices(void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	return osm_ucast_mgr_build_lid_matrices(context);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_build_lfts(void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	return ucast_mgr_build_lfts(context);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
Packit Service 54dbc3
{
Packit Service 54dbc3
	r->context = &osm->sm.ucast_mgr;
Packit Service 54dbc3
	r->build_lid_matrices = ucast_build_lid_matrices;
Packit Service 54dbc3
	r->ucast_build_fwd_tables = ucast_build_lfts;
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int ucast_dor_build_lfts(void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ucast_mgr_t *mgr = context;
Packit Service 54dbc3
	int ret;
Packit Service 54dbc3
Packit Service 54dbc3
	mgr->is_dor = 1;
Packit Service 54dbc3
	ret = ucast_mgr_build_lfts(mgr);
Packit Service 54dbc3
	mgr->is_dor = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	return ret;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
Packit Service 54dbc3
{
Packit Service 54dbc3
	r->context = &osm->sm.ucast_mgr;
Packit Service 54dbc3
	r->build_lid_matrices = ucast_build_lid_matrices;
Packit Service 54dbc3
	r->ucast_build_fwd_tables = ucast_dor_build_lfts;
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int ucast_dummy_build_lid_matrices(void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}