1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5d6b92ffaSHans Petter Selasky  *
6d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11d6b92ffaSHans Petter Selasky  *
12d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14d6b92ffaSHans Petter Selasky  *     conditions are met:
15d6b92ffaSHans Petter Selasky  *
16d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18d6b92ffaSHans Petter Selasky  *        disclaimer.
19d6b92ffaSHans Petter Selasky  *
20d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24d6b92ffaSHans Petter Selasky  *
25d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32d6b92ffaSHans Petter Selasky  * SOFTWARE.
33d6b92ffaSHans Petter Selasky  *
34d6b92ffaSHans Petter Selasky  */
35d6b92ffaSHans Petter Selasky 
36d6b92ffaSHans Petter Selasky /*
37d6b92ffaSHans Petter Selasky  * Abstract:
38d6b92ffaSHans Petter Selasky  *    Implementation of osm_ucast_mgr_t.
39d6b92ffaSHans Petter Selasky  * This file implements the Unicast Manager object.
40d6b92ffaSHans Petter Selasky  */
41d6b92ffaSHans Petter Selasky 
42d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
43d6b92ffaSHans Petter Selasky #  include <config.h>
44d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
45d6b92ffaSHans Petter Selasky 
46d6b92ffaSHans Petter Selasky #include <stdio.h>
47d6b92ffaSHans Petter Selasky #include <stdlib.h>
48d6b92ffaSHans Petter Selasky #include <string.h>
49d6b92ffaSHans Petter Selasky #include <ctype.h>
50d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
51d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h>
52d6b92ffaSHans Petter Selasky #include <complib/cl_debug.h>
53d6b92ffaSHans Petter Selasky #include <complib/cl_qlist.h>
54d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
55d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_UCAST_MGR_C
56d6b92ffaSHans Petter Selasky #include <opensm/osm_ucast_mgr.h>
57d6b92ffaSHans Petter Selasky #include <opensm/osm_sm.h>
58d6b92ffaSHans Petter Selasky #include <opensm/osm_log.h>
59d6b92ffaSHans Petter Selasky #include <opensm/osm_node.h>
60d6b92ffaSHans Petter Selasky #include <opensm/osm_switch.h>
61d6b92ffaSHans Petter Selasky #include <opensm/osm_helper.h>
62d6b92ffaSHans Petter Selasky #include <opensm/osm_msgdef.h>
63d6b92ffaSHans Petter Selasky #include <opensm/osm_opensm.h>
64d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr)65d6b92ffaSHans Petter Selasky void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr)
66d6b92ffaSHans Petter Selasky {
67d6b92ffaSHans Petter Selasky 	memset(p_mgr, 0, sizeof(*p_mgr));
68d6b92ffaSHans Petter Selasky }
69d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr)70d6b92ffaSHans Petter Selasky void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr)
71d6b92ffaSHans Petter Selasky {
72d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_mgr);
73d6b92ffaSHans Petter Selasky 
74d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
75d6b92ffaSHans Petter Selasky 
76d6b92ffaSHans Petter Selasky 	if (p_mgr->cache_valid)
77d6b92ffaSHans Petter Selasky 		osm_ucast_cache_invalidate(p_mgr);
78d6b92ffaSHans Petter Selasky 
79d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
80d6b92ffaSHans Petter Selasky }
81d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr,IN osm_sm_t * sm)82d6b92ffaSHans Petter Selasky ib_api_status_t osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr, IN osm_sm_t * sm)
83d6b92ffaSHans Petter Selasky {
84d6b92ffaSHans Petter Selasky 	ib_api_status_t status = IB_SUCCESS;
85d6b92ffaSHans Petter Selasky 
86d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(sm->p_log);
87d6b92ffaSHans Petter Selasky 
88d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_construct(p_mgr);
89d6b92ffaSHans Petter Selasky 
90d6b92ffaSHans Petter Selasky 	p_mgr->sm = sm;
91d6b92ffaSHans Petter Selasky 	p_mgr->p_log = sm->p_log;
92d6b92ffaSHans Petter Selasky 	p_mgr->p_subn = sm->p_subn;
93d6b92ffaSHans Petter Selasky 	p_mgr->p_lock = sm->p_lock;
94d6b92ffaSHans Petter Selasky 
95d6b92ffaSHans Petter Selasky 	if (sm->p_subn->opt.use_ucast_cache)
96d6b92ffaSHans Petter Selasky 		cl_qmap_init(&p_mgr->cache_sw_tbl);
97d6b92ffaSHans Petter Selasky 
98d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
99d6b92ffaSHans Petter Selasky 	return status;
100d6b92ffaSHans Petter Selasky }
101d6b92ffaSHans Petter Selasky 
102d6b92ffaSHans Petter Selasky /**********************************************************************
103d6b92ffaSHans Petter Selasky  Add each switch's own and neighbor LIDs to its LID matrix
104d6b92ffaSHans Petter Selasky **********************************************************************/
ucast_mgr_process_hop_0_1(IN cl_map_item_t * p_map_item,IN void * context)105d6b92ffaSHans Petter Selasky static void ucast_mgr_process_hop_0_1(IN cl_map_item_t * p_map_item,
106d6b92ffaSHans Petter Selasky 				      IN void *context)
107d6b92ffaSHans Petter Selasky {
108d6b92ffaSHans Petter Selasky 	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
109d6b92ffaSHans Petter Selasky 	osm_node_t *p_remote_node;
110d6b92ffaSHans Petter Selasky 	uint16_t lid, remote_lid;
111d6b92ffaSHans Petter Selasky 	uint8_t i;
112d6b92ffaSHans Petter Selasky 
113d6b92ffaSHans Petter Selasky 	lid = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
114d6b92ffaSHans Petter Selasky 	osm_switch_set_hops(p_sw, lid, 0, 0);
115d6b92ffaSHans Petter Selasky 
116d6b92ffaSHans Petter Selasky 	for (i = 1; i < p_sw->num_ports; i++) {
117d6b92ffaSHans Petter Selasky 		osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, i);
118d6b92ffaSHans Petter Selasky 		p_remote_node = (p && p->p_remote_physp) ?
119d6b92ffaSHans Petter Selasky 		    p->p_remote_physp->p_node : NULL;
120d6b92ffaSHans Petter Selasky 
121d6b92ffaSHans Petter Selasky 		if (p_remote_node && p_remote_node->sw &&
122d6b92ffaSHans Petter Selasky 		    p_remote_node != p_sw->p_node) {
123d6b92ffaSHans Petter Selasky 			remote_lid = osm_node_get_base_lid(p_remote_node, 0);
124d6b92ffaSHans Petter Selasky 			remote_lid = cl_ntoh16(remote_lid);
125d6b92ffaSHans Petter Selasky 			osm_switch_set_hops(p_sw, remote_lid, i, p->hop_wf);
126d6b92ffaSHans Petter Selasky 		}
127d6b92ffaSHans Petter Selasky 	}
128d6b92ffaSHans Petter Selasky }
129d6b92ffaSHans Petter Selasky 
ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * p_mgr,IN osm_switch_t * p_this_sw,IN osm_switch_t * p_remote_sw,IN uint8_t port_num,IN uint8_t remote_port_num)130d6b92ffaSHans Petter Selasky static void ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * p_mgr,
131d6b92ffaSHans Petter Selasky 				       IN osm_switch_t * p_this_sw,
132d6b92ffaSHans Petter Selasky 				       IN osm_switch_t * p_remote_sw,
133d6b92ffaSHans Petter Selasky 				       IN uint8_t port_num,
134d6b92ffaSHans Petter Selasky 				       IN uint8_t remote_port_num)
135d6b92ffaSHans Petter Selasky {
136d6b92ffaSHans Petter Selasky 	osm_switch_t *p_sw;
137d6b92ffaSHans Petter Selasky 	cl_map_item_t *item;
138d6b92ffaSHans Petter Selasky 	uint16_t lid_ho;
139d6b92ffaSHans Petter Selasky 	uint16_t hops;
140d6b92ffaSHans Petter Selasky 	osm_physp_t *p;
141d6b92ffaSHans Petter Selasky 
142d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
143d6b92ffaSHans Petter Selasky 
144d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
145d6b92ffaSHans Petter Selasky 		"Node 0x%" PRIx64 ", remote node 0x%" PRIx64
146d6b92ffaSHans Petter Selasky 		", port %u, remote port %u\n",
147d6b92ffaSHans Petter Selasky 		cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
148d6b92ffaSHans Petter Selasky 		cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
149d6b92ffaSHans Petter Selasky 		port_num, remote_port_num);
150d6b92ffaSHans Petter Selasky 
151d6b92ffaSHans Petter Selasky 	p = osm_node_get_physp_ptr(p_this_sw->p_node, port_num);
152d6b92ffaSHans Petter Selasky 
153d6b92ffaSHans Petter Selasky 	for (item = cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
154d6b92ffaSHans Petter Selasky 	     item != cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl);
155d6b92ffaSHans Petter Selasky 	     item = cl_qmap_next(item)) {
156d6b92ffaSHans Petter Selasky 		p_sw = (osm_switch_t *) item;
157d6b92ffaSHans Petter Selasky 		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
158d6b92ffaSHans Petter Selasky 		hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
159d6b92ffaSHans Petter Selasky 		if (hops == OSM_NO_PATH)
160d6b92ffaSHans Petter Selasky 			continue;
161d6b92ffaSHans Petter Selasky 		hops += p->hop_wf;
162d6b92ffaSHans Petter Selasky 		if (hops <
163d6b92ffaSHans Petter Selasky 		    osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
164d6b92ffaSHans Petter Selasky 			if (osm_switch_set_hops
165d6b92ffaSHans Petter Selasky 			    (p_this_sw, lid_ho, port_num, (uint8_t) hops) != 0)
166d6b92ffaSHans Petter Selasky 				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A03: "
167d6b92ffaSHans Petter Selasky 					"cannot set hops for lid %u at switch 0x%"
168d6b92ffaSHans Petter Selasky 					PRIx64 "\n", lid_ho,
169d6b92ffaSHans Petter Selasky 					cl_ntoh64(osm_node_get_node_guid
170d6b92ffaSHans Petter Selasky 						  (p_this_sw->p_node)));
171d6b92ffaSHans Petter Selasky 			p_mgr->some_hop_count_set = TRUE;
172d6b92ffaSHans Petter Selasky 		}
173d6b92ffaSHans Petter Selasky 	}
174d6b92ffaSHans Petter Selasky 
175d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
176d6b92ffaSHans Petter Selasky }
177d6b92ffaSHans Petter Selasky 
find_and_add_remote_sys(osm_switch_t * sw,uint8_t port,boolean_t dor,struct osm_remote_guids_count * r)178d6b92ffaSHans Petter Selasky static struct osm_remote_node *find_and_add_remote_sys(osm_switch_t * sw,
179d6b92ffaSHans Petter Selasky 						       uint8_t port,
180d6b92ffaSHans Petter Selasky 						       boolean_t dor, struct
181d6b92ffaSHans Petter Selasky 						       osm_remote_guids_count
182d6b92ffaSHans Petter Selasky 						       *r)
183d6b92ffaSHans Petter Selasky {
184d6b92ffaSHans Petter Selasky 	unsigned i;
185d6b92ffaSHans Petter Selasky 	osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
186d6b92ffaSHans Petter Selasky 	osm_node_t *node = p->p_remote_physp->p_node;
187d6b92ffaSHans Petter Selasky 	uint8_t rem_port = osm_physp_get_port_num(p->p_remote_physp);
188d6b92ffaSHans Petter Selasky 
189d6b92ffaSHans Petter Selasky 	for (i = 0; i < r->count; i++)
190d6b92ffaSHans Petter Selasky 		if (r->guids[i].node == node)
191d6b92ffaSHans Petter Selasky 			if (!dor || (r->guids[i].port == rem_port))
192d6b92ffaSHans Petter Selasky 				return &r->guids[i];
193d6b92ffaSHans Petter Selasky 
194d6b92ffaSHans Petter Selasky 	r->guids[i].node = node;
195d6b92ffaSHans Petter Selasky 	r->guids[i].forwarded_to = 0;
196d6b92ffaSHans Petter Selasky 	r->guids[i].port = rem_port;
197d6b92ffaSHans Petter Selasky 	r->count++;
198d6b92ffaSHans Petter Selasky 	return &r->guids[i];
199d6b92ffaSHans Petter Selasky }
200d6b92ffaSHans Petter Selasky 
ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr,IN osm_switch_t * p_sw,IN osm_port_t * p_port,IN unsigned lid_offset)201d6b92ffaSHans Petter Selasky static void ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr,
202d6b92ffaSHans Petter Selasky 				   IN osm_switch_t * p_sw,
203d6b92ffaSHans Petter Selasky 				   IN osm_port_t * p_port,
204d6b92ffaSHans Petter Selasky 				   IN unsigned lid_offset)
205d6b92ffaSHans Petter Selasky {
206d6b92ffaSHans Petter Selasky 	uint16_t min_lid_ho;
207d6b92ffaSHans Petter Selasky 	uint16_t max_lid_ho;
208d6b92ffaSHans Petter Selasky 	uint16_t lid_ho;
209d6b92ffaSHans Petter Selasky 	uint8_t port;
210d6b92ffaSHans Petter Selasky 	boolean_t is_ignored_by_port_prof;
211d6b92ffaSHans Petter Selasky 	ib_net64_t node_guid;
212d6b92ffaSHans Petter Selasky 	unsigned start_from = 1;
213d6b92ffaSHans Petter Selasky 
214d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
215d6b92ffaSHans Petter Selasky 
216d6b92ffaSHans Petter Selasky 	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
217d6b92ffaSHans Petter Selasky 
218d6b92ffaSHans Petter Selasky 	/* If the lids are zero - then there was some problem with
219d6b92ffaSHans Petter Selasky 	 * the initialization. Don't handle this port. */
220d6b92ffaSHans Petter Selasky 	if (min_lid_ho == 0 || max_lid_ho == 0) {
221d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
222d6b92ffaSHans Petter Selasky 			"Port 0x%" PRIx64 " (%s port %d) has LID 0. An "
223d6b92ffaSHans Petter Selasky 			"initialization error occurred. Ignoring port\n",
224d6b92ffaSHans Petter Selasky 			cl_ntoh64(osm_port_get_guid(p_port)),
225d6b92ffaSHans Petter Selasky 			p_port->p_node->print_desc,
226d6b92ffaSHans Petter Selasky 			p_port->p_physp->port_num);
227d6b92ffaSHans Petter Selasky 		goto Exit;
228d6b92ffaSHans Petter Selasky 	}
229d6b92ffaSHans Petter Selasky 
230d6b92ffaSHans Petter Selasky 	lid_ho = min_lid_ho + lid_offset;
231d6b92ffaSHans Petter Selasky 
232d6b92ffaSHans Petter Selasky 	if (lid_ho > max_lid_ho)
233d6b92ffaSHans Petter Selasky 		goto Exit;
234d6b92ffaSHans Petter Selasky 
235d6b92ffaSHans Petter Selasky 	if (lid_offset && !p_mgr->is_dor)
236d6b92ffaSHans Petter Selasky 		/* ignore potential overflow - it is handled in osm_switch.c */
237d6b92ffaSHans Petter Selasky 		start_from =
238d6b92ffaSHans Petter Selasky 		    osm_switch_get_port_by_lid(p_sw, lid_ho - 1, OSM_NEW_LFT) + 1;
239d6b92ffaSHans Petter Selasky 
240d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
241d6b92ffaSHans Petter Selasky 		"Processing port 0x%" PRIx64
242d6b92ffaSHans Petter Selasky 		" (\'%s\' port %u), LID %u [%u,%u]\n",
243d6b92ffaSHans Petter Selasky 		cl_ntoh64(osm_port_get_guid(p_port)),
244d6b92ffaSHans Petter Selasky 		p_port->p_node->print_desc, p_port->p_physp->port_num, lid_ho,
245d6b92ffaSHans Petter Selasky 		min_lid_ho, max_lid_ho);
246d6b92ffaSHans Petter Selasky 
247d6b92ffaSHans Petter Selasky 	/* TODO - This should be runtime error, not a CL_ASSERT() */
248d6b92ffaSHans Petter Selasky 	CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO);
249d6b92ffaSHans Petter Selasky 
250d6b92ffaSHans Petter Selasky 	node_guid = osm_node_get_node_guid(p_sw->p_node);
251d6b92ffaSHans Petter Selasky 
252d6b92ffaSHans Petter Selasky 	/*
253d6b92ffaSHans Petter Selasky 	   The lid matrix contains the number of hops to each
254d6b92ffaSHans Petter Selasky 	   lid from each port.  From this information we determine
255d6b92ffaSHans Petter Selasky 	   how best to distribute the LID range across the ports
256d6b92ffaSHans Petter Selasky 	   that can reach those LIDs.
257d6b92ffaSHans Petter Selasky 	 */
258d6b92ffaSHans Petter Selasky 	port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
259d6b92ffaSHans Petter Selasky 					 p_mgr->p_subn->ignore_existing_lfts,
260d6b92ffaSHans Petter Selasky 					 p_mgr->p_subn->opt.lmc,
261d6b92ffaSHans Petter Selasky 					 p_mgr->is_dor,
262d6b92ffaSHans Petter Selasky 					 p_mgr->p_subn->opt.port_shifting,
263d6b92ffaSHans Petter Selasky 					 !lid_offset && p_port->use_scatter,
264d6b92ffaSHans Petter Selasky 					 OSM_LFT);
265d6b92ffaSHans Petter Selasky 
266d6b92ffaSHans Petter Selasky 	if (port == OSM_NO_PATH) {
267d6b92ffaSHans Petter Selasky 		/* do not try to overwrite the ppro of non existing port ... */
268d6b92ffaSHans Petter Selasky 		is_ignored_by_port_prof = TRUE;
269d6b92ffaSHans Petter Selasky 
270d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
271d6b92ffaSHans Petter Selasky 			"No path to get to LID %u from switch 0x%" PRIx64 "\n",
272d6b92ffaSHans Petter Selasky 			lid_ho, cl_ntoh64(node_guid));
273d6b92ffaSHans Petter Selasky 	} else {
274d6b92ffaSHans Petter Selasky 		osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
275d6b92ffaSHans Petter Selasky 		if (!p)
276d6b92ffaSHans Petter Selasky 			goto Exit;
277d6b92ffaSHans Petter Selasky 
278d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
279d6b92ffaSHans Petter Selasky 			"Routing LID %u to port %u for switch 0x%" PRIx64 "\n",
280d6b92ffaSHans Petter Selasky 			lid_ho, port, cl_ntoh64(node_guid));
281d6b92ffaSHans Petter Selasky 
282d6b92ffaSHans Petter Selasky 		/*
283d6b92ffaSHans Petter Selasky 		   we would like to optionally ignore this port in equalization
284d6b92ffaSHans Petter Selasky 		   as in the case of the Mellanox Anafa Internal PCI TCA port
285d6b92ffaSHans Petter Selasky 		 */
286d6b92ffaSHans Petter Selasky 		is_ignored_by_port_prof = p->is_prof_ignored;
287d6b92ffaSHans Petter Selasky 
288d6b92ffaSHans Petter Selasky 		/*
289d6b92ffaSHans Petter Selasky 		   We also would ignore this route if the target lid is of
290d6b92ffaSHans Petter Selasky 		   a switch and the port_profile_switch_node is not TRUE
291d6b92ffaSHans Petter Selasky 		 */
292d6b92ffaSHans Petter Selasky 		if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
293d6b92ffaSHans Petter Selasky 			is_ignored_by_port_prof |=
294d6b92ffaSHans Petter Selasky 			    (osm_node_get_type(p_port->p_node) ==
295d6b92ffaSHans Petter Selasky 			     IB_NODE_TYPE_SWITCH);
296d6b92ffaSHans Petter Selasky 	}
297d6b92ffaSHans Petter Selasky 
298d6b92ffaSHans Petter Selasky 	/*
299d6b92ffaSHans Petter Selasky 	   We have selected the port for this LID.
300d6b92ffaSHans Petter Selasky 	   Write it to the forwarding tables.
301d6b92ffaSHans Petter Selasky 	 */
302d6b92ffaSHans Petter Selasky 	p_sw->new_lft[lid_ho] = port;
303d6b92ffaSHans Petter Selasky 	if (!is_ignored_by_port_prof) {
304d6b92ffaSHans Petter Selasky 		struct osm_remote_node *rem_node_used;
305d6b92ffaSHans Petter Selasky 		osm_switch_count_path(p_sw, port);
306d6b92ffaSHans Petter Selasky 		if (port > 0 && p_port->priv &&
307d6b92ffaSHans Petter Selasky 		    (rem_node_used = find_and_add_remote_sys(p_sw, port,
308d6b92ffaSHans Petter Selasky 							     p_mgr->is_dor,
309d6b92ffaSHans Petter Selasky 							     p_port->priv)))
310d6b92ffaSHans Petter Selasky 			rem_node_used->forwarded_to++;
311d6b92ffaSHans Petter Selasky 	}
312d6b92ffaSHans Petter Selasky 
313d6b92ffaSHans Petter Selasky Exit:
314d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
315d6b92ffaSHans Petter Selasky }
316d6b92ffaSHans Petter Selasky 
alloc_ports_priv(osm_ucast_mgr_t * mgr)317d6b92ffaSHans Petter Selasky static void alloc_ports_priv(osm_ucast_mgr_t * mgr)
318d6b92ffaSHans Petter Selasky {
319d6b92ffaSHans Petter Selasky 	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
320d6b92ffaSHans Petter Selasky 	struct osm_remote_guids_count *r;
321d6b92ffaSHans Petter Selasky 	osm_port_t *port;
322d6b92ffaSHans Petter Selasky 	cl_map_item_t *item;
323d6b92ffaSHans Petter Selasky 	unsigned lmc;
324d6b92ffaSHans Petter Selasky 
325d6b92ffaSHans Petter Selasky 	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
326d6b92ffaSHans Petter Selasky 	     item = cl_qmap_next(item)) {
327d6b92ffaSHans Petter Selasky 		port = (osm_port_t *) item;
328d6b92ffaSHans Petter Selasky 		lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
329d6b92ffaSHans Petter Selasky 		r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
330d6b92ffaSHans Petter Selasky 		if (!r) {
331d6b92ffaSHans Petter Selasky 			OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
332d6b92ffaSHans Petter Selasky 				"cannot allocate memory to track remote"
333d6b92ffaSHans Petter Selasky 				" systems for lmc > 0\n");
334d6b92ffaSHans Petter Selasky 			port->priv = NULL;
335d6b92ffaSHans Petter Selasky 			continue;
336d6b92ffaSHans Petter Selasky 		}
337d6b92ffaSHans Petter Selasky 		memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
338d6b92ffaSHans Petter Selasky 		port->priv = r;
339d6b92ffaSHans Petter Selasky 	}
340d6b92ffaSHans Petter Selasky }
341d6b92ffaSHans Petter Selasky 
free_ports_priv(osm_ucast_mgr_t * mgr)342d6b92ffaSHans Petter Selasky static void free_ports_priv(osm_ucast_mgr_t * mgr)
343d6b92ffaSHans Petter Selasky {
344d6b92ffaSHans Petter Selasky 	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
345d6b92ffaSHans Petter Selasky 	osm_port_t *port;
346d6b92ffaSHans Petter Selasky 	cl_map_item_t *item;
347d6b92ffaSHans Petter Selasky 	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
348d6b92ffaSHans Petter Selasky 	     item = cl_qmap_next(item)) {
349d6b92ffaSHans Petter Selasky 		port = (osm_port_t *) item;
350d6b92ffaSHans Petter Selasky 		if (port->priv) {
351d6b92ffaSHans Petter Selasky 			free(port->priv);
352d6b92ffaSHans Petter Selasky 			port->priv = NULL;
353d6b92ffaSHans Petter Selasky 		}
354d6b92ffaSHans Petter Selasky 	}
355d6b92ffaSHans Petter Selasky }
356d6b92ffaSHans Petter Selasky 
ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item,IN void * context)357d6b92ffaSHans Petter Selasky static void ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item,
358d6b92ffaSHans Petter Selasky 				  IN void *context)
359d6b92ffaSHans Petter Selasky {
360d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *p_mgr = context;
361d6b92ffaSHans Petter Selasky 	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
362d6b92ffaSHans Petter Selasky 	unsigned i, lids_per_port;
363d6b92ffaSHans Petter Selasky 
364d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
365d6b92ffaSHans Petter Selasky 
366d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_sw && p_sw->p_node);
367d6b92ffaSHans Petter Selasky 
368d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
369d6b92ffaSHans Petter Selasky 		"Processing switch 0x%" PRIx64 "\n",
370d6b92ffaSHans Petter Selasky 		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
371d6b92ffaSHans Petter Selasky 
372d6b92ffaSHans Petter Selasky 	/* Initialize LIDs in buffer to invalid port number. */
373d6b92ffaSHans Petter Selasky 	memset(p_sw->new_lft, OSM_NO_PATH, p_sw->max_lid_ho + 1);
374d6b92ffaSHans Petter Selasky 
375d6b92ffaSHans Petter Selasky 	alloc_ports_priv(p_mgr);
376d6b92ffaSHans Petter Selasky 
377d6b92ffaSHans Petter Selasky 	/*
378d6b92ffaSHans Petter Selasky 	   Iterate through every port setting LID routes for each
379d6b92ffaSHans Petter Selasky 	   port based on base LID and LMC value.
380d6b92ffaSHans Petter Selasky 	 */
381d6b92ffaSHans Petter Selasky 	lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
382d6b92ffaSHans Petter Selasky 	for (i = 0; i < lids_per_port; i++) {
383d6b92ffaSHans Petter Selasky 		cl_qlist_t *list = &p_mgr->port_order_list;
384d6b92ffaSHans Petter Selasky 		cl_list_item_t *item;
385d6b92ffaSHans Petter Selasky 		for (item = cl_qlist_head(list); item != cl_qlist_end(list);
386d6b92ffaSHans Petter Selasky 		     item = cl_qlist_next(item)) {
387d6b92ffaSHans Petter Selasky 			osm_port_t *port = cl_item_obj(item, port, list_item);
388d6b92ffaSHans Petter Selasky 			ucast_mgr_process_port(p_mgr, p_sw, port, i);
389d6b92ffaSHans Petter Selasky 		}
390d6b92ffaSHans Petter Selasky 	}
391d6b92ffaSHans Petter Selasky 
392d6b92ffaSHans Petter Selasky 	free_ports_priv(p_mgr);
393d6b92ffaSHans Petter Selasky 
394d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
395d6b92ffaSHans Petter Selasky }
396d6b92ffaSHans Petter Selasky 
ucast_mgr_process_neighbors(IN cl_map_item_t * p_map_item,IN void * context)397d6b92ffaSHans Petter Selasky static void ucast_mgr_process_neighbors(IN cl_map_item_t * p_map_item,
398d6b92ffaSHans Petter Selasky 					IN void *context)
399d6b92ffaSHans Petter Selasky {
400d6b92ffaSHans Petter Selasky 	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
401d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t * p_mgr = context;
402d6b92ffaSHans Petter Selasky 	osm_node_t *p_node;
403d6b92ffaSHans Petter Selasky 	osm_node_t *p_remote_node;
404d6b92ffaSHans Petter Selasky 	uint32_t port_num;
405d6b92ffaSHans Petter Selasky 	uint8_t remote_port_num;
406d6b92ffaSHans Petter Selasky 	uint32_t num_ports;
407d6b92ffaSHans Petter Selasky 	osm_physp_t *p_physp;
408d6b92ffaSHans Petter Selasky 
409d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
410d6b92ffaSHans Petter Selasky 
411d6b92ffaSHans Petter Selasky 	p_node = p_sw->p_node;
412d6b92ffaSHans Petter Selasky 
413d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_node);
414d6b92ffaSHans Petter Selasky 	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
415d6b92ffaSHans Petter Selasky 
416d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
417d6b92ffaSHans Petter Selasky 		"Processing switch with GUID 0x%" PRIx64 "\n",
418d6b92ffaSHans Petter Selasky 		cl_ntoh64(osm_node_get_node_guid(p_node)));
419d6b92ffaSHans Petter Selasky 
420d6b92ffaSHans Petter Selasky 	num_ports = osm_node_get_num_physp(p_node);
421d6b92ffaSHans Petter Selasky 
422d6b92ffaSHans Petter Selasky 	/*
423d6b92ffaSHans Petter Selasky 	   Start with port 1 to skip the switch's management port.
424d6b92ffaSHans Petter Selasky 	 */
425d6b92ffaSHans Petter Selasky 	for (port_num = 1; port_num < num_ports; port_num++) {
426d6b92ffaSHans Petter Selasky 		p_remote_node = osm_node_get_remote_node(p_node,
427d6b92ffaSHans Petter Selasky 							 (uint8_t) port_num,
428d6b92ffaSHans Petter Selasky 							 &remote_port_num);
429d6b92ffaSHans Petter Selasky 		if (p_remote_node && p_remote_node->sw
430d6b92ffaSHans Petter Selasky 		    && (p_remote_node != p_node)) {
431d6b92ffaSHans Petter Selasky 			/* make sure the link is healthy. If it is not - don't
432d6b92ffaSHans Petter Selasky 			   propagate through it. */
433d6b92ffaSHans Petter Selasky 			p_physp = osm_node_get_physp_ptr(p_node, port_num);
434d6b92ffaSHans Petter Selasky 			if (!p_physp || !osm_link_is_healthy(p_physp))
435d6b92ffaSHans Petter Selasky 				continue;
436d6b92ffaSHans Petter Selasky 
437d6b92ffaSHans Petter Selasky 			ucast_mgr_process_neighbor(p_mgr, p_sw,
438d6b92ffaSHans Petter Selasky 						   p_remote_node->sw,
439d6b92ffaSHans Petter Selasky 						   (uint8_t) port_num,
440d6b92ffaSHans Petter Selasky 						   remote_port_num);
441d6b92ffaSHans Petter Selasky 		}
442d6b92ffaSHans Petter Selasky 	}
443d6b92ffaSHans Petter Selasky 
444d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
445d6b92ffaSHans Petter Selasky }
446d6b92ffaSHans Petter Selasky 
set_hop_wf(void * ctx,uint64_t guid,char * p)447d6b92ffaSHans Petter Selasky static int set_hop_wf(void *ctx, uint64_t guid, char *p)
448d6b92ffaSHans Petter Selasky {
449d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *m = ctx;
450d6b92ffaSHans Petter Selasky 	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
451d6b92ffaSHans Petter Selasky 	osm_physp_t *physp;
452d6b92ffaSHans Petter Selasky 	unsigned port, hop_wf;
453d6b92ffaSHans Petter Selasky 	char *e;
454d6b92ffaSHans Petter Selasky 
455d6b92ffaSHans Petter Selasky 	if (!node || !node->sw) {
456d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
457d6b92ffaSHans Petter Selasky 			"switch with guid 0x%016" PRIx64 " is not found\n",
458d6b92ffaSHans Petter Selasky 			guid);
459d6b92ffaSHans Petter Selasky 		return 0;
460d6b92ffaSHans Petter Selasky 	}
461d6b92ffaSHans Petter Selasky 
462d6b92ffaSHans Petter Selasky 	if (!p || !*p || !(port = strtoul(p, &e, 0)) || (p == e) ||
463d6b92ffaSHans Petter Selasky 	    port >= node->sw->num_ports) {
464d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
465d6b92ffaSHans Petter Selasky 			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
466d6b92ffaSHans Petter Selasky 		return 0;
467d6b92ffaSHans Petter Selasky 	}
468d6b92ffaSHans Petter Selasky 
469d6b92ffaSHans Petter Selasky 	p = e + 1;
470d6b92ffaSHans Petter Selasky 
471d6b92ffaSHans Petter Selasky 	if (!*p || !(hop_wf = strtoul(p, &e, 0)) || p == e || hop_wf >= 0x100) {
472d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
473d6b92ffaSHans Petter Selasky 			"bad hop weight factor specified for guid 0x%016" PRIx64
474d6b92ffaSHans Petter Selasky 			"port %u\n", guid, port);
475d6b92ffaSHans Petter Selasky 		return 0;
476d6b92ffaSHans Petter Selasky 	}
477d6b92ffaSHans Petter Selasky 
478d6b92ffaSHans Petter Selasky 	physp = osm_node_get_physp_ptr(node, port);
479d6b92ffaSHans Petter Selasky 	if (!physp)
480d6b92ffaSHans Petter Selasky 		return 0;
481d6b92ffaSHans Petter Selasky 
482d6b92ffaSHans Petter Selasky 	physp->hop_wf = hop_wf;
483d6b92ffaSHans Petter Selasky 
484d6b92ffaSHans Petter Selasky 	return 0;
485d6b92ffaSHans Petter Selasky }
486d6b92ffaSHans Petter Selasky 
set_default_hop_wf(cl_map_item_t * p_map_item,void * ctx)487d6b92ffaSHans Petter Selasky static void set_default_hop_wf(cl_map_item_t * p_map_item, void *ctx)
488d6b92ffaSHans Petter Selasky {
489d6b92ffaSHans Petter Selasky 	osm_switch_t *sw = (osm_switch_t *) p_map_item;
490d6b92ffaSHans Petter Selasky 	int i;
491d6b92ffaSHans Petter Selasky 
492d6b92ffaSHans Petter Selasky 	for (i = 1; i < sw->num_ports; i++) {
493d6b92ffaSHans Petter Selasky 		osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
494d6b92ffaSHans Petter Selasky 		if (p)
495d6b92ffaSHans Petter Selasky 			p->hop_wf = 1;
496d6b92ffaSHans Petter Selasky 	}
497d6b92ffaSHans Petter Selasky }
498d6b92ffaSHans Petter Selasky 
set_search_ordering_ports(void * ctx,uint64_t guid,char * p)499d6b92ffaSHans Petter Selasky static int set_search_ordering_ports(void *ctx, uint64_t guid, char *p)
500d6b92ffaSHans Petter Selasky {
501d6b92ffaSHans Petter Selasky 	osm_subn_t *p_subn = ctx;
502d6b92ffaSHans Petter Selasky 	osm_node_t *node = osm_get_node_by_guid(p_subn, cl_hton64(guid));
503d6b92ffaSHans Petter Selasky 	osm_switch_t *sw;
504d6b92ffaSHans Petter Selasky 	uint8_t *search_ordering_ports = NULL;
505d6b92ffaSHans Petter Selasky 	uint8_t port;
506d6b92ffaSHans Petter Selasky 	unsigned int *ports = NULL;
507d6b92ffaSHans Petter Selasky 	const int bpw = sizeof(*ports)*8;
508d6b92ffaSHans Petter Selasky 	int words;
509d6b92ffaSHans Petter Selasky 	int i = 1; /* port 0 maps to port 0 */
510d6b92ffaSHans Petter Selasky 
511d6b92ffaSHans Petter Selasky 	if (!node || !(sw = node->sw)) {
512d6b92ffaSHans Petter Selasky 		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
513d6b92ffaSHans Petter Selasky 			"switch with guid 0x%016" PRIx64 " is not found\n",
514d6b92ffaSHans Petter Selasky 			guid);
515d6b92ffaSHans Petter Selasky 		return 0;
516d6b92ffaSHans Petter Selasky 	}
517d6b92ffaSHans Petter Selasky 
518d6b92ffaSHans Petter Selasky 	if (sw->search_ordering_ports) {
519d6b92ffaSHans Petter Selasky 		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
520d6b92ffaSHans Petter Selasky 			"switch with guid 0x%016" PRIx64 " already listed\n",
521d6b92ffaSHans Petter Selasky 			guid);
522d6b92ffaSHans Petter Selasky 		return 0;
523d6b92ffaSHans Petter Selasky 	}
524d6b92ffaSHans Petter Selasky 
525d6b92ffaSHans Petter Selasky 	search_ordering_ports = malloc(sizeof(*search_ordering_ports)*sw->num_ports);
526d6b92ffaSHans Petter Selasky 	if (!search_ordering_ports) {
527d6b92ffaSHans Petter Selasky 		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
528d6b92ffaSHans Petter Selasky 			"ERR 3A07: cannot allocate memory for search_ordering_ports\n");
529d6b92ffaSHans Petter Selasky 		return -1;
530d6b92ffaSHans Petter Selasky 	}
531d6b92ffaSHans Petter Selasky 	memset(search_ordering_ports, 0, sizeof(*search_ordering_ports)*sw->num_ports);
532d6b92ffaSHans Petter Selasky 
533d6b92ffaSHans Petter Selasky 	/* the ports array is for record keeping of which ports have
534d6b92ffaSHans Petter Selasky 	 * been seen */
535d6b92ffaSHans Petter Selasky 	words = (sw->num_ports + bpw - 1)/bpw;
536d6b92ffaSHans Petter Selasky 	ports = malloc(words*sizeof(*ports));
537d6b92ffaSHans Petter Selasky 	if (!ports) {
538d6b92ffaSHans Petter Selasky 		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
539d6b92ffaSHans Petter Selasky 			"ERR 3A08: cannot allocate memory for ports\n");
540d6b92ffaSHans Petter Selasky 		free(search_ordering_ports);
541d6b92ffaSHans Petter Selasky 		return -1;
542d6b92ffaSHans Petter Selasky 	}
543d6b92ffaSHans Petter Selasky 	memset(ports, 0, words*sizeof(*ports));
544d6b92ffaSHans Petter Selasky 
545d6b92ffaSHans Petter Selasky 	while ((*p != '\0') && (*p != '#')) {
546d6b92ffaSHans Petter Selasky 		char *e;
547d6b92ffaSHans Petter Selasky 
548d6b92ffaSHans Petter Selasky 		port = strtoul(p, &e, 0);
549d6b92ffaSHans Petter Selasky 		if ((p == e) || (port == 0) || (port >= sw->num_ports) ||
550d6b92ffaSHans Petter Selasky 		    !osm_node_get_physp_ptr(node, port)) {
551d6b92ffaSHans Petter Selasky 			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
552d6b92ffaSHans Petter Selasky 				"bad port %d specified for guid 0x%016" PRIx64 "\n",
553d6b92ffaSHans Petter Selasky 				port, guid);
554d6b92ffaSHans Petter Selasky 			free(search_ordering_ports);
555d6b92ffaSHans Petter Selasky 			free(ports);
556d6b92ffaSHans Petter Selasky 			return 0;
557d6b92ffaSHans Petter Selasky 		}
558d6b92ffaSHans Petter Selasky 
559d6b92ffaSHans Petter Selasky 		if (ports[port/bpw] & (1u << (port%bpw))) {
560d6b92ffaSHans Petter Selasky 			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
561d6b92ffaSHans Petter Selasky 				"port %d already specified for guid 0x%016" PRIx64 "\n",
562d6b92ffaSHans Petter Selasky 				port, guid);
563d6b92ffaSHans Petter Selasky 			free(search_ordering_ports);
564d6b92ffaSHans Petter Selasky 			free(ports);
565d6b92ffaSHans Petter Selasky 			return 0;
566d6b92ffaSHans Petter Selasky 		}
567d6b92ffaSHans Petter Selasky 
568d6b92ffaSHans Petter Selasky 		ports[port/bpw] |= (1u << (port%bpw));
569d6b92ffaSHans Petter Selasky 		search_ordering_ports[i++] = port;
570d6b92ffaSHans Petter Selasky 
571d6b92ffaSHans Petter Selasky 		p = e;
572d6b92ffaSHans Petter Selasky 		while (isspace(*p)) {
573d6b92ffaSHans Petter Selasky 			p++;
574d6b92ffaSHans Petter Selasky 		}
575d6b92ffaSHans Petter Selasky 	}
576d6b92ffaSHans Petter Selasky 
577d6b92ffaSHans Petter Selasky 	if (i > 1) {
578d6b92ffaSHans Petter Selasky 		for (port = 1; port < sw->num_ports; port++) {
579d6b92ffaSHans Petter Selasky 			/* fill out the rest of the search_ordering_ports array
580d6b92ffaSHans Petter Selasky 			 * in sequence using the remaining unspecified
581d6b92ffaSHans Petter Selasky 			 * ports.
582d6b92ffaSHans Petter Selasky 			 */
583d6b92ffaSHans Petter Selasky 			if (!(ports[port/bpw] & (1u << (port%bpw)))) {
584d6b92ffaSHans Petter Selasky 				search_ordering_ports[i++] = port;
585d6b92ffaSHans Petter Selasky 			}
586d6b92ffaSHans Petter Selasky 		}
587d6b92ffaSHans Petter Selasky 		sw->search_ordering_ports = search_ordering_ports;
588d6b92ffaSHans Petter Selasky 	} else {
589d6b92ffaSHans Petter Selasky 		free(search_ordering_ports);
590d6b92ffaSHans Petter Selasky 	}
591d6b92ffaSHans Petter Selasky 
592d6b92ffaSHans Petter Selasky 	free(ports);
593d6b92ffaSHans Petter Selasky 	return 0;
594d6b92ffaSHans Petter Selasky }
595d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr)596d6b92ffaSHans Petter Selasky int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr)
597d6b92ffaSHans Petter Selasky {
598d6b92ffaSHans Petter Selasky 	uint32_t i;
599d6b92ffaSHans Petter Selasky 	uint32_t iteration_max;
600d6b92ffaSHans Petter Selasky 	cl_qmap_t *p_sw_guid_tbl;
601d6b92ffaSHans Petter Selasky 
602d6b92ffaSHans Petter Selasky 	p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
603d6b92ffaSHans Petter Selasky 
604d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
605d6b92ffaSHans Petter Selasky 		"Starting switches' Min Hop Table Assignment\n");
606d6b92ffaSHans Petter Selasky 
607d6b92ffaSHans Petter Selasky 	/*
608d6b92ffaSHans Petter Selasky 	   Set up the weighting factors for the routing.
609d6b92ffaSHans Petter Selasky 	 */
610d6b92ffaSHans Petter Selasky 	cl_qmap_apply_func(p_sw_guid_tbl, set_default_hop_wf, NULL);
611d6b92ffaSHans Petter Selasky 	if (p_mgr->p_subn->opt.hop_weights_file) {
612d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
613d6b92ffaSHans Petter Selasky 			"Fetching hop weight factor file \'%s\'\n",
614d6b92ffaSHans Petter Selasky 			p_mgr->p_subn->opt.hop_weights_file);
615d6b92ffaSHans Petter Selasky 		if (parse_node_map(p_mgr->p_subn->opt.hop_weights_file,
616d6b92ffaSHans Petter Selasky 				   set_hop_wf, p_mgr)) {
617d6b92ffaSHans Petter Selasky 			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: "
618d6b92ffaSHans Petter Selasky 				"cannot parse hop_weights_file \'%s\'\n",
619d6b92ffaSHans Petter Selasky 				p_mgr->p_subn->opt.hop_weights_file);
620d6b92ffaSHans Petter Selasky 		}
621d6b92ffaSHans Petter Selasky 	}
622d6b92ffaSHans Petter Selasky 
623d6b92ffaSHans Petter Selasky 	/*
624d6b92ffaSHans Petter Selasky 	   Set the switch matrices for each switch's own port 0 LID(s)
625d6b92ffaSHans Petter Selasky 	   then set the lid matrices for the each switch's leaf nodes.
626d6b92ffaSHans Petter Selasky 	 */
627d6b92ffaSHans Petter Selasky 	cl_qmap_apply_func(p_sw_guid_tbl, ucast_mgr_process_hop_0_1, p_mgr);
628d6b92ffaSHans Petter Selasky 
629d6b92ffaSHans Petter Selasky 	/*
630d6b92ffaSHans Petter Selasky 	   Get the switch matrices for each switch's neighbors.
631d6b92ffaSHans Petter Selasky 	   This process requires a number of iterations equal to
632d6b92ffaSHans Petter Selasky 	   the number of switches in the subnet minus 1.
633d6b92ffaSHans Petter Selasky 
634d6b92ffaSHans Petter Selasky 	   In each iteration, a switch learns the lid/port/hop
635d6b92ffaSHans Petter Selasky 	   information (as contained by a switch's lid matrix) from
636d6b92ffaSHans Petter Selasky 	   its immediate neighbors.  After each iteration, a switch
637d6b92ffaSHans Petter Selasky 	   (and it's neighbors) know more routing information than
638d6b92ffaSHans Petter Selasky 	   it did on the previous iteration.
639d6b92ffaSHans Petter Selasky 	   Thus, by repeatedly absorbing the routing information of
640d6b92ffaSHans Petter Selasky 	   neighbor switches, every switch eventually learns how to
641d6b92ffaSHans Petter Selasky 	   route all LIDs on the subnet.
642d6b92ffaSHans Petter Selasky 
643d6b92ffaSHans Petter Selasky 	   Note that there may not be any switches in the subnet if
644d6b92ffaSHans Petter Selasky 	   we are in simple p2p configuration.
645d6b92ffaSHans Petter Selasky 	 */
646d6b92ffaSHans Petter Selasky 	iteration_max = cl_qmap_count(p_sw_guid_tbl);
647d6b92ffaSHans Petter Selasky 
648d6b92ffaSHans Petter Selasky 	/*
649d6b92ffaSHans Petter Selasky 	   If there are switches in the subnet, iterate until the lid
650d6b92ffaSHans Petter Selasky 	   matrix has been constructed.  Otherwise, just immediately
651d6b92ffaSHans Petter Selasky 	   indicate we're done if no switches exist.
652d6b92ffaSHans Petter Selasky 	 */
653d6b92ffaSHans Petter Selasky 	if (iteration_max) {
654d6b92ffaSHans Petter Selasky 		iteration_max--;
655d6b92ffaSHans Petter Selasky 
656d6b92ffaSHans Petter Selasky 		/*
657d6b92ffaSHans Petter Selasky 		   we need to find out when the propagation of
658d6b92ffaSHans Petter Selasky 		   hop counts has relaxed. So this global variable
659d6b92ffaSHans Petter Selasky 		   is preset to 0 on each iteration and if
660d6b92ffaSHans Petter Selasky 		   if non of the switches was set will exit the
661d6b92ffaSHans Petter Selasky 		   while loop
662d6b92ffaSHans Petter Selasky 		 */
663d6b92ffaSHans Petter Selasky 		p_mgr->some_hop_count_set = TRUE;
664d6b92ffaSHans Petter Selasky 		for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
665d6b92ffaSHans Petter Selasky 		     i++) {
666d6b92ffaSHans Petter Selasky 			p_mgr->some_hop_count_set = FALSE;
667d6b92ffaSHans Petter Selasky 			cl_qmap_apply_func(p_sw_guid_tbl,
668d6b92ffaSHans Petter Selasky 					   ucast_mgr_process_neighbors, p_mgr);
669d6b92ffaSHans Petter Selasky 		}
670d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
671d6b92ffaSHans Petter Selasky 			"Min-hop propagated in %d steps\n", i);
672d6b92ffaSHans Petter Selasky 	}
673d6b92ffaSHans Petter Selasky 
674d6b92ffaSHans Petter Selasky 	return 0;
675d6b92ffaSHans Petter Selasky }
676d6b92ffaSHans Petter Selasky 
ucast_mgr_setup_all_switches(osm_subn_t * p_subn)677d6b92ffaSHans Petter Selasky static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
678d6b92ffaSHans Petter Selasky {
679d6b92ffaSHans Petter Selasky 	osm_switch_t *p_sw;
680d6b92ffaSHans Petter Selasky 	uint16_t lids;
681d6b92ffaSHans Petter Selasky 
682d6b92ffaSHans Petter Selasky 	lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);
683d6b92ffaSHans Petter Selasky 	lids = lids ? lids - 1 : 0;
684d6b92ffaSHans Petter Selasky 
685d6b92ffaSHans Petter Selasky 	for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
686d6b92ffaSHans Petter Selasky 	     p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl);
687d6b92ffaSHans Petter Selasky 	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {
688d6b92ffaSHans Petter Selasky 		if (osm_switch_prepare_path_rebuild(p_sw, lids)) {
689d6b92ffaSHans Petter Selasky 			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: "
690d6b92ffaSHans Petter Selasky 				"cannot setup switch 0x%016" PRIx64 "\n",
691d6b92ffaSHans Petter Selasky 				cl_ntoh64(osm_node_get_node_guid
692d6b92ffaSHans Petter Selasky 					  (p_sw->p_node)));
693d6b92ffaSHans Petter Selasky 			return -1;
694d6b92ffaSHans Petter Selasky 		}
695d6b92ffaSHans Petter Selasky 		if (p_sw->search_ordering_ports) {
696d6b92ffaSHans Petter Selasky 			free(p_sw->search_ordering_ports);
697d6b92ffaSHans Petter Selasky 			p_sw->search_ordering_ports = NULL;
698d6b92ffaSHans Petter Selasky 		}
699d6b92ffaSHans Petter Selasky 	}
700d6b92ffaSHans Petter Selasky 
701d6b92ffaSHans Petter Selasky 	if (p_subn->opt.port_search_ordering_file) {
702d6b92ffaSHans Petter Selasky 		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_DEBUG,
703d6b92ffaSHans Petter Selasky 			"Fetching dimension ports file \'%s\'\n",
704d6b92ffaSHans Petter Selasky 			p_subn->opt.port_search_ordering_file);
705d6b92ffaSHans Petter Selasky 		if (parse_node_map(p_subn->opt.port_search_ordering_file,
706d6b92ffaSHans Petter Selasky 				   set_search_ordering_ports, p_subn)) {
707d6b92ffaSHans Petter Selasky 			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0F: "
708d6b92ffaSHans Petter Selasky 				"cannot parse port_search_ordering_file \'%s\'\n",
709d6b92ffaSHans Petter Selasky 				p_subn->opt.port_search_ordering_file);
710d6b92ffaSHans Petter Selasky 		}
711d6b92ffaSHans Petter Selasky 	}
712d6b92ffaSHans Petter Selasky 
713d6b92ffaSHans Petter Selasky 	return 0;
714d6b92ffaSHans Petter Selasky }
715d6b92ffaSHans Petter Selasky 
add_guid_to_order_list(void * ctx,uint64_t guid,char * p)716d6b92ffaSHans Petter Selasky static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
717d6b92ffaSHans Petter Selasky {
718d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *m = ctx;
719d6b92ffaSHans Petter Selasky 	osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
720d6b92ffaSHans Petter Selasky 
721d6b92ffaSHans Petter Selasky 	if (!port) {
722d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
723d6b92ffaSHans Petter Selasky 			"port guid not found: 0x%016" PRIx64 "\n", guid);
724d6b92ffaSHans Petter Selasky 		return 0;
725d6b92ffaSHans Petter Selasky 	}
726d6b92ffaSHans Petter Selasky 
727d6b92ffaSHans Petter Selasky 	if (port->flag) {
728d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
729d6b92ffaSHans Petter Selasky 			"port guid specified multiple times 0x%016" PRIx64 "\n",
730d6b92ffaSHans Petter Selasky 			guid);
731d6b92ffaSHans Petter Selasky 		return 0;
732d6b92ffaSHans Petter Selasky 	}
733d6b92ffaSHans Petter Selasky 
734d6b92ffaSHans Petter Selasky 	cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
735d6b92ffaSHans Petter Selasky 	port->flag = 1;
736d6b92ffaSHans Petter Selasky 	port->use_scatter =  (m->p_subn->opt.guid_routing_order_no_scatter == TRUE) ? 0 : m->p_subn->opt.scatter_ports;
737d6b92ffaSHans Petter Selasky 
738d6b92ffaSHans Petter Selasky 	return 0;
739d6b92ffaSHans Petter Selasky }
740d6b92ffaSHans Petter Selasky 
add_port_to_order_list(cl_map_item_t * p_map_item,void * ctx)741d6b92ffaSHans Petter Selasky static void add_port_to_order_list(cl_map_item_t * p_map_item, void *ctx)
742d6b92ffaSHans Petter Selasky {
743d6b92ffaSHans Petter Selasky 	osm_port_t *port = (osm_port_t *) p_map_item;
744d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *m = ctx;
745d6b92ffaSHans Petter Selasky 
746d6b92ffaSHans Petter Selasky 	if (!port->flag) {
747d6b92ffaSHans Petter Selasky 		port->use_scatter = m->p_subn->opt.scatter_ports;
748d6b92ffaSHans Petter Selasky 		cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
749d6b92ffaSHans Petter Selasky 	} else
750d6b92ffaSHans Petter Selasky 		port->flag = 0;
751d6b92ffaSHans Petter Selasky }
752d6b92ffaSHans Petter Selasky 
mark_ignored_port(void * ctx,uint64_t guid,char * p)753d6b92ffaSHans Petter Selasky static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
754d6b92ffaSHans Petter Selasky {
755d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *m = ctx;
756d6b92ffaSHans Petter Selasky 	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
757d6b92ffaSHans Petter Selasky 	osm_physp_t *physp;
758d6b92ffaSHans Petter Selasky 	unsigned port;
759d6b92ffaSHans Petter Selasky 
760d6b92ffaSHans Petter Selasky 	if (!node || !node->sw) {
761d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
762d6b92ffaSHans Petter Selasky 			"switch with guid 0x%016" PRIx64 " is not found\n",
763d6b92ffaSHans Petter Selasky 			guid);
764d6b92ffaSHans Petter Selasky 		return 0;
765d6b92ffaSHans Petter Selasky 	}
766d6b92ffaSHans Petter Selasky 
767d6b92ffaSHans Petter Selasky 	if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
768d6b92ffaSHans Petter Selasky 	    port >= node->sw->num_ports) {
769d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
770d6b92ffaSHans Petter Selasky 			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
771d6b92ffaSHans Petter Selasky 		return 0;
772d6b92ffaSHans Petter Selasky 	}
773d6b92ffaSHans Petter Selasky 
774d6b92ffaSHans Petter Selasky 	physp = osm_node_get_physp_ptr(node, port);
775d6b92ffaSHans Petter Selasky 	if (!physp)
776d6b92ffaSHans Petter Selasky 		return 0;
777d6b92ffaSHans Petter Selasky 
778d6b92ffaSHans Petter Selasky 	physp->is_prof_ignored = 1;
779d6b92ffaSHans Petter Selasky 
780d6b92ffaSHans Petter Selasky 	return 0;
781d6b92ffaSHans Petter Selasky }
782d6b92ffaSHans Petter Selasky 
clear_prof_ignore_flag(cl_map_item_t * p_map_item,void * ctx)783d6b92ffaSHans Petter Selasky static void clear_prof_ignore_flag(cl_map_item_t * p_map_item, void *ctx)
784d6b92ffaSHans Petter Selasky {
785d6b92ffaSHans Petter Selasky 	osm_switch_t *sw = (osm_switch_t *) p_map_item;
786d6b92ffaSHans Petter Selasky 	int i;
787d6b92ffaSHans Petter Selasky 
788d6b92ffaSHans Petter Selasky 	for (i = 1; i < sw->num_ports; i++) {
789d6b92ffaSHans Petter Selasky 		osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
790d6b92ffaSHans Petter Selasky 		if (p)
791d6b92ffaSHans Petter Selasky 			p->is_prof_ignored = 0;
792d6b92ffaSHans Petter Selasky 	}
793d6b92ffaSHans Petter Selasky }
794d6b92ffaSHans Petter Selasky 
add_sw_endports_to_order_list(osm_switch_t * sw,osm_ucast_mgr_t * m)795d6b92ffaSHans Petter Selasky static void add_sw_endports_to_order_list(osm_switch_t * sw,
796d6b92ffaSHans Petter Selasky 					  osm_ucast_mgr_t * m)
797d6b92ffaSHans Petter Selasky {
798d6b92ffaSHans Petter Selasky 	osm_port_t *port;
799d6b92ffaSHans Petter Selasky 	osm_physp_t *p;
800d6b92ffaSHans Petter Selasky 	int i;
801d6b92ffaSHans Petter Selasky 
802d6b92ffaSHans Petter Selasky 	for (i = 1; i < sw->num_ports; i++) {
803d6b92ffaSHans Petter Selasky 		p = osm_node_get_physp_ptr(sw->p_node, i);
804d6b92ffaSHans Petter Selasky 		if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) {
805d6b92ffaSHans Petter Selasky 			port = osm_get_port_by_guid(m->p_subn,
806d6b92ffaSHans Petter Selasky 						    p->p_remote_physp->
807d6b92ffaSHans Petter Selasky 						    port_guid);
808d6b92ffaSHans Petter Selasky 			if (!port || port->flag)
809d6b92ffaSHans Petter Selasky 				continue;
810d6b92ffaSHans Petter Selasky 			cl_qlist_insert_tail(&m->port_order_list,
811d6b92ffaSHans Petter Selasky 					     &port->list_item);
812d6b92ffaSHans Petter Selasky 			port->flag = 1;
813d6b92ffaSHans Petter Selasky 			port->use_scatter = m->p_subn->opt.scatter_ports;
814d6b92ffaSHans Petter Selasky 		}
815d6b92ffaSHans Petter Selasky 	}
816d6b92ffaSHans Petter Selasky }
817d6b92ffaSHans Petter Selasky 
sw_count_endport_links(osm_switch_t * sw)818d6b92ffaSHans Petter Selasky static void sw_count_endport_links(osm_switch_t * sw)
819d6b92ffaSHans Petter Selasky {
820d6b92ffaSHans Petter Selasky 	osm_physp_t *p;
821d6b92ffaSHans Petter Selasky 	int i;
822d6b92ffaSHans Petter Selasky 
823d6b92ffaSHans Petter Selasky 	sw->endport_links = 0;
824d6b92ffaSHans Petter Selasky 	for (i = 1; i < sw->num_ports; i++) {
825d6b92ffaSHans Petter Selasky 		p = osm_node_get_physp_ptr(sw->p_node, i);
826d6b92ffaSHans Petter Selasky 		if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw)
827d6b92ffaSHans Petter Selasky 			sw->endport_links++;
828d6b92ffaSHans Petter Selasky 	}
829d6b92ffaSHans Petter Selasky }
830d6b92ffaSHans Petter Selasky 
compar_sw_load(const void * s1,const void * s2)831d6b92ffaSHans Petter Selasky static int compar_sw_load(const void *s1, const void *s2)
832d6b92ffaSHans Petter Selasky {
833d6b92ffaSHans Petter Selasky #define get_sw_endport_links(s) (*(osm_switch_t **)s)->endport_links
834d6b92ffaSHans Petter Selasky 	return get_sw_endport_links(s2) - get_sw_endport_links(s1);
835d6b92ffaSHans Petter Selasky }
836d6b92ffaSHans Petter Selasky 
sort_ports_by_switch_load(osm_ucast_mgr_t * m)837d6b92ffaSHans Petter Selasky static void sort_ports_by_switch_load(osm_ucast_mgr_t * m)
838d6b92ffaSHans Petter Selasky {
839d6b92ffaSHans Petter Selasky 	int i, num = cl_qmap_count(&m->p_subn->sw_guid_tbl);
840d6b92ffaSHans Petter Selasky 	void **s = malloc(num * sizeof(*s));
841d6b92ffaSHans Petter Selasky 	if (!s) {
842d6b92ffaSHans Petter Selasky 		OSM_LOG(m->p_log, OSM_LOG_ERROR, "ERR 3A0C: "
843d6b92ffaSHans Petter Selasky 			"No memory, skip by switch load sorting.\n");
844d6b92ffaSHans Petter Selasky 		return;
845d6b92ffaSHans Petter Selasky 	}
846d6b92ffaSHans Petter Selasky 	s[0] = cl_qmap_head(&m->p_subn->sw_guid_tbl);
847d6b92ffaSHans Petter Selasky 	for (i = 1; i < num; i++)
848d6b92ffaSHans Petter Selasky 		s[i] = cl_qmap_next(s[i - 1]);
849d6b92ffaSHans Petter Selasky 
850d6b92ffaSHans Petter Selasky 	for (i = 0; i < num; i++)
851d6b92ffaSHans Petter Selasky 		sw_count_endport_links(s[i]);
852d6b92ffaSHans Petter Selasky 
853d6b92ffaSHans Petter Selasky 	qsort(s, num, sizeof(*s), compar_sw_load);
854d6b92ffaSHans Petter Selasky 
855d6b92ffaSHans Petter Selasky 	for (i = 0; i < num; i++)
856d6b92ffaSHans Petter Selasky 		add_sw_endports_to_order_list(s[i], m);
857d6b92ffaSHans Petter Selasky 	free(s);
858d6b92ffaSHans Petter Selasky }
859d6b92ffaSHans Petter Selasky 
ucast_mgr_build_lfts(osm_ucast_mgr_t * p_mgr)860d6b92ffaSHans Petter Selasky static int ucast_mgr_build_lfts(osm_ucast_mgr_t * p_mgr)
861d6b92ffaSHans Petter Selasky {
862d6b92ffaSHans Petter Selasky 	cl_qlist_init(&p_mgr->port_order_list);
863d6b92ffaSHans Petter Selasky 
864d6b92ffaSHans Petter Selasky 	if (p_mgr->p_subn->opt.guid_routing_order_file) {
865d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
866d6b92ffaSHans Petter Selasky 			"Fetching guid routing order file \'%s\'\n",
867d6b92ffaSHans Petter Selasky 			p_mgr->p_subn->opt.guid_routing_order_file);
868d6b92ffaSHans Petter Selasky 
869d6b92ffaSHans Petter Selasky 		if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
870d6b92ffaSHans Petter Selasky 				   add_guid_to_order_list, p_mgr))
871d6b92ffaSHans Petter Selasky 			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0D: "
872d6b92ffaSHans Petter Selasky 				"cannot parse guid routing order file \'%s\'\n",
873d6b92ffaSHans Petter Selasky 				p_mgr->p_subn->opt.guid_routing_order_file);
874d6b92ffaSHans Petter Selasky 	}
875d6b92ffaSHans Petter Selasky 	sort_ports_by_switch_load(p_mgr);
876d6b92ffaSHans Petter Selasky 
877d6b92ffaSHans Petter Selasky 	if (p_mgr->p_subn->opt.port_prof_ignore_file) {
878d6b92ffaSHans Petter Selasky 		cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
879d6b92ffaSHans Petter Selasky 				   clear_prof_ignore_flag, NULL);
880d6b92ffaSHans Petter Selasky 		if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
881d6b92ffaSHans Petter Selasky 				   mark_ignored_port, p_mgr)) {
882d6b92ffaSHans Petter Selasky 			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0E: "
883d6b92ffaSHans Petter Selasky 				"cannot parse port prof ignore file \'%s\'\n",
884d6b92ffaSHans Petter Selasky 				p_mgr->p_subn->opt.port_prof_ignore_file);
885d6b92ffaSHans Petter Selasky 		}
886d6b92ffaSHans Petter Selasky 	}
887d6b92ffaSHans Petter Selasky 
888d6b92ffaSHans Petter Selasky 	cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
889d6b92ffaSHans Petter Selasky 			   add_port_to_order_list, p_mgr);
890d6b92ffaSHans Petter Selasky 
891d6b92ffaSHans Petter Selasky 	cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_process_tbl,
892d6b92ffaSHans Petter Selasky 			   p_mgr);
893d6b92ffaSHans Petter Selasky 
894d6b92ffaSHans Petter Selasky 	cl_qlist_remove_all(&p_mgr->port_order_list);
895d6b92ffaSHans Petter Selasky 
896d6b92ffaSHans Petter Selasky 	return 0;
897d6b92ffaSHans Petter Selasky }
898d6b92ffaSHans Petter Selasky 
ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item,IN void * cxt)899d6b92ffaSHans Petter Selasky static void ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item,
900d6b92ffaSHans Petter Selasky 				  IN void *cxt)
901d6b92ffaSHans Petter Selasky {
902d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *p_mgr = cxt;
903d6b92ffaSHans Petter Selasky 	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
904d6b92ffaSHans Petter Selasky 	osm_node_t *p_node;
905d6b92ffaSHans Petter Selasky 	osm_physp_t *p_physp;
906d6b92ffaSHans Petter Selasky 	osm_dr_path_t *p_path;
907d6b92ffaSHans Petter Selasky 	osm_madw_context_t context;
908d6b92ffaSHans Petter Selasky 	ib_api_status_t status;
909d6b92ffaSHans Petter Selasky 	ib_switch_info_t si;
910d6b92ffaSHans Petter Selasky 	boolean_t set_swinfo_require = FALSE;
911d6b92ffaSHans Petter Selasky 	uint16_t lin_top;
912d6b92ffaSHans Petter Selasky 	uint8_t life_state;
913d6b92ffaSHans Petter Selasky 
914d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_mgr);
915d6b92ffaSHans Petter Selasky 
916d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
917d6b92ffaSHans Petter Selasky 
918d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_sw && p_sw->max_lid_ho);
919d6b92ffaSHans Petter Selasky 
920d6b92ffaSHans Petter Selasky 	p_node = p_sw->p_node;
921d6b92ffaSHans Petter Selasky 
922d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_node);
923d6b92ffaSHans Petter Selasky 
924d6b92ffaSHans Petter Selasky 	if (p_mgr->max_lid < p_sw->max_lid_ho)
925d6b92ffaSHans Petter Selasky 		p_mgr->max_lid = p_sw->max_lid_ho;
926d6b92ffaSHans Petter Selasky 
927d6b92ffaSHans Petter Selasky 	p_physp = osm_node_get_physp_ptr(p_node, 0);
928d6b92ffaSHans Petter Selasky 
929d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_physp);
930d6b92ffaSHans Petter Selasky 
931d6b92ffaSHans Petter Selasky 	p_path = osm_physp_get_dr_path_ptr(p_physp);
932d6b92ffaSHans Petter Selasky 
933d6b92ffaSHans Petter Selasky 	/*
934d6b92ffaSHans Petter Selasky 	   Set the top of the unicast forwarding table.
935d6b92ffaSHans Petter Selasky 	 */
936d6b92ffaSHans Petter Selasky 	si = p_sw->switch_info;
937d6b92ffaSHans Petter Selasky 	lin_top = cl_hton16(p_sw->max_lid_ho);
938d6b92ffaSHans Petter Selasky 	if (lin_top != si.lin_top) {
939d6b92ffaSHans Petter Selasky 		set_swinfo_require = TRUE;
940d6b92ffaSHans Petter Selasky 		si.lin_top = lin_top;
941d6b92ffaSHans Petter Selasky 		context.si_context.lft_top_change = TRUE;
942d6b92ffaSHans Petter Selasky 	} else
943d6b92ffaSHans Petter Selasky 		context.si_context.lft_top_change = FALSE;
944d6b92ffaSHans Petter Selasky 
945d6b92ffaSHans Petter Selasky 	life_state = si.life_state;
946d6b92ffaSHans Petter Selasky 	ib_switch_info_set_life_time(&si, p_mgr->p_subn->opt.packet_life_time);
947d6b92ffaSHans Petter Selasky 
948d6b92ffaSHans Petter Selasky 	if (life_state != si.life_state)
949d6b92ffaSHans Petter Selasky 		set_swinfo_require = TRUE;
950d6b92ffaSHans Petter Selasky 
951d6b92ffaSHans Petter Selasky 	if (set_swinfo_require) {
952d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
953d6b92ffaSHans Petter Selasky 			"Setting switch FT top to LID %u\n", p_sw->max_lid_ho);
954d6b92ffaSHans Petter Selasky 
955d6b92ffaSHans Petter Selasky 		context.si_context.light_sweep = FALSE;
956d6b92ffaSHans Petter Selasky 		context.si_context.node_guid = osm_node_get_node_guid(p_node);
957d6b92ffaSHans Petter Selasky 		context.si_context.set_method = TRUE;
958d6b92ffaSHans Petter Selasky 
959d6b92ffaSHans Petter Selasky 		status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
960d6b92ffaSHans Petter Selasky 				     sizeof(si), IB_MAD_ATTR_SWITCH_INFO,
961d6b92ffaSHans Petter Selasky 				     0, FALSE,
962d6b92ffaSHans Petter Selasky 				     ib_port_info_get_m_key(&p_physp->port_info),
963d6b92ffaSHans Petter Selasky 				     CL_DISP_MSGID_NONE, &context);
964d6b92ffaSHans Petter Selasky 
965d6b92ffaSHans Petter Selasky 		if (status != IB_SUCCESS)
966d6b92ffaSHans Petter Selasky 			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
967d6b92ffaSHans Petter Selasky 				"Sending SwitchInfo attribute failed (%s)\n",
968d6b92ffaSHans Petter Selasky 				ib_get_err_str(status));
969d6b92ffaSHans Petter Selasky 	}
970d6b92ffaSHans Petter Selasky 
971d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
972d6b92ffaSHans Petter Selasky }
973d6b92ffaSHans Petter Selasky 
set_lft_block(IN osm_switch_t * p_sw,IN osm_ucast_mgr_t * p_mgr,IN uint16_t block_id_ho)974d6b92ffaSHans Petter Selasky static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr,
975d6b92ffaSHans Petter Selasky 			 IN uint16_t block_id_ho)
976d6b92ffaSHans Petter Selasky {
977d6b92ffaSHans Petter Selasky 	osm_madw_context_t context;
978d6b92ffaSHans Petter Selasky 	osm_dr_path_t *p_path;
979d6b92ffaSHans Petter Selasky 	osm_physp_t *p_physp;
980d6b92ffaSHans Petter Selasky 	ib_api_status_t status;
981d6b92ffaSHans Petter Selasky 
982d6b92ffaSHans Petter Selasky 	/*
983d6b92ffaSHans Petter Selasky 	   Send linear forwarding table blocks to the switch
984d6b92ffaSHans Petter Selasky 	   as long as the switch indicates it has blocks needing
985d6b92ffaSHans Petter Selasky 	   configuration.
986d6b92ffaSHans Petter Selasky 	 */
987d6b92ffaSHans Petter Selasky 	if (!p_sw->new_lft) {
988d6b92ffaSHans Petter Selasky 		/* any routing should provide the new_lft */
989d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
990d6b92ffaSHans Petter Selasky 			  p_mgr->cache_valid && !p_sw->need_update);
991d6b92ffaSHans Petter Selasky 		return -1;
992d6b92ffaSHans Petter Selasky 	}
993d6b92ffaSHans Petter Selasky 
994d6b92ffaSHans Petter Selasky 	p_physp = osm_node_get_physp_ptr(p_sw->p_node, 0);
995d6b92ffaSHans Petter Selasky 	if (!p_physp)
996d6b92ffaSHans Petter Selasky 		return -1;
997d6b92ffaSHans Petter Selasky 
998d6b92ffaSHans Petter Selasky 	p_path = osm_physp_get_dr_path_ptr(p_physp);
999d6b92ffaSHans Petter Selasky 
1000d6b92ffaSHans Petter Selasky 	context.lft_context.node_guid = osm_node_get_node_guid(p_sw->p_node);
1001d6b92ffaSHans Petter Selasky 	context.lft_context.set_method = TRUE;
1002d6b92ffaSHans Petter Selasky 
1003d6b92ffaSHans Petter Selasky 	if (!p_sw->need_update && !p_mgr->p_subn->need_update &&
1004d6b92ffaSHans Petter Selasky 	    !memcmp(p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
1005d6b92ffaSHans Petter Selasky 		    p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE,
1006d6b92ffaSHans Petter Selasky 		    IB_SMP_DATA_SIZE))
1007d6b92ffaSHans Petter Selasky 		return 0;
1008d6b92ffaSHans Petter Selasky 
1009d6b92ffaSHans Petter Selasky 	/*
1010d6b92ffaSHans Petter Selasky 	 * Zero the stored LFT block, so in case the MAD will end up
1011d6b92ffaSHans Petter Selasky 	 * with error, we will resend it in the next sweep.
1012d6b92ffaSHans Petter Selasky 	 */
1013d6b92ffaSHans Petter Selasky 	memset(p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, 0,
1014d6b92ffaSHans Petter Selasky 	       IB_SMP_DATA_SIZE);
1015d6b92ffaSHans Petter Selasky 
1016d6b92ffaSHans Petter Selasky 	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
1017d6b92ffaSHans Petter Selasky 		"Writing FT block %u to switch 0x%" PRIx64 "\n", block_id_ho,
1018d6b92ffaSHans Petter Selasky 		cl_ntoh64(context.lft_context.node_guid));
1019d6b92ffaSHans Petter Selasky 
1020d6b92ffaSHans Petter Selasky 	status = osm_req_set(p_mgr->sm, p_path,
1021d6b92ffaSHans Petter Selasky 			     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
1022d6b92ffaSHans Petter Selasky 			     IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL,
1023d6b92ffaSHans Petter Selasky 			     cl_hton32(block_id_ho), FALSE,
1024d6b92ffaSHans Petter Selasky 			     ib_port_info_get_m_key(&p_physp->port_info),
1025d6b92ffaSHans Petter Selasky 			     CL_DISP_MSGID_NONE, &context);
1026d6b92ffaSHans Petter Selasky 
1027d6b92ffaSHans Petter Selasky 	if (status != IB_SUCCESS) {
1028d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A10: "
1029d6b92ffaSHans Petter Selasky 			"Sending linear fwd. tbl. block failed (%s)\n",
1030d6b92ffaSHans Petter Selasky 			ib_get_err_str(status));
1031d6b92ffaSHans Petter Selasky 		return -1;
1032d6b92ffaSHans Petter Selasky 	}
1033d6b92ffaSHans Petter Selasky 
1034d6b92ffaSHans Petter Selasky 	return 0;
1035d6b92ffaSHans Petter Selasky }
1036d6b92ffaSHans Petter Selasky 
ucast_mgr_pipeline_fwd_tbl(osm_ucast_mgr_t * p_mgr)1037d6b92ffaSHans Petter Selasky static void ucast_mgr_pipeline_fwd_tbl(osm_ucast_mgr_t * p_mgr)
1038d6b92ffaSHans Petter Selasky {
1039d6b92ffaSHans Petter Selasky 	cl_qmap_t *tbl;
1040d6b92ffaSHans Petter Selasky 	cl_map_item_t *item;
1041d6b92ffaSHans Petter Selasky 	unsigned i, max_block = p_mgr->max_lid / IB_SMP_DATA_SIZE + 1;
1042d6b92ffaSHans Petter Selasky 
1043d6b92ffaSHans Petter Selasky 	tbl = &p_mgr->p_subn->sw_guid_tbl;
1044d6b92ffaSHans Petter Selasky 	for (i = 0; i < max_block; i++)
1045d6b92ffaSHans Petter Selasky 		for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl);
1046d6b92ffaSHans Petter Selasky 		     item = cl_qmap_next(item))
1047d6b92ffaSHans Petter Selasky 			set_lft_block((osm_switch_t *)item, p_mgr, i);
1048d6b92ffaSHans Petter Selasky }
1049d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_set_fwd_tables(osm_ucast_mgr_t * p_mgr)1050d6b92ffaSHans Petter Selasky void osm_ucast_mgr_set_fwd_tables(osm_ucast_mgr_t * p_mgr)
1051d6b92ffaSHans Petter Selasky {
1052d6b92ffaSHans Petter Selasky 	p_mgr->max_lid = 0;
1053d6b92ffaSHans Petter Selasky 
1054d6b92ffaSHans Petter Selasky 	cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_set_fwd_top,
1055d6b92ffaSHans Petter Selasky 			   p_mgr);
1056d6b92ffaSHans Petter Selasky 
1057d6b92ffaSHans Petter Selasky 	ucast_mgr_pipeline_fwd_tbl(p_mgr);
1058d6b92ffaSHans Petter Selasky }
1059d6b92ffaSHans Petter Selasky 
ucast_mgr_route(struct osm_routing_engine * r,osm_opensm_t * osm)1060d6b92ffaSHans Petter Selasky static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t * osm)
1061d6b92ffaSHans Petter Selasky {
1062d6b92ffaSHans Petter Selasky 	int ret;
1063d6b92ffaSHans Petter Selasky 
1064d6b92ffaSHans Petter Selasky 	OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
1065d6b92ffaSHans Petter Selasky 		"building routing with \'%s\' routing algorithm...\n", r->name);
1066d6b92ffaSHans Petter Selasky 
1067d6b92ffaSHans Petter Selasky 	/* Set the before each lft build to keep the routes in place between sweeps */
1068d6b92ffaSHans Petter Selasky 	if (osm->subn.opt.scatter_ports)
1069d6b92ffaSHans Petter Selasky 		srandom(osm->subn.opt.scatter_ports);
1070d6b92ffaSHans Petter Selasky 
1071d6b92ffaSHans Petter Selasky 	if (!r->build_lid_matrices ||
1072d6b92ffaSHans Petter Selasky 	    (ret = r->build_lid_matrices(r->context)) > 0)
1073d6b92ffaSHans Petter Selasky 		ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr);
1074d6b92ffaSHans Petter Selasky 
1075d6b92ffaSHans Petter Selasky 	if (ret < 0) {
1076d6b92ffaSHans Petter Selasky 		OSM_LOG(&osm->log, OSM_LOG_ERROR,
1077d6b92ffaSHans Petter Selasky 			"%s: cannot build lid matrices\n", r->name);
1078d6b92ffaSHans Petter Selasky 		return ret;
1079d6b92ffaSHans Petter Selasky 	}
1080d6b92ffaSHans Petter Selasky 
1081d6b92ffaSHans Petter Selasky 	if (!r->ucast_build_fwd_tables ||
1082d6b92ffaSHans Petter Selasky 	    (ret = r->ucast_build_fwd_tables(r->context)) > 0)
1083d6b92ffaSHans Petter Selasky 		ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr);
1084d6b92ffaSHans Petter Selasky 
1085d6b92ffaSHans Petter Selasky 	if (ret < 0) {
1086d6b92ffaSHans Petter Selasky 		OSM_LOG(&osm->log, OSM_LOG_ERROR,
1087d6b92ffaSHans Petter Selasky 			"%s: cannot build fwd tables\n", r->name);
1088d6b92ffaSHans Petter Selasky 		return ret;
1089d6b92ffaSHans Petter Selasky 	}
1090d6b92ffaSHans Petter Selasky 
1091d6b92ffaSHans Petter Selasky 	osm->routing_engine_used = r;
1092d6b92ffaSHans Petter Selasky 
1093d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_set_fwd_tables(&osm->sm.ucast_mgr);
1094d6b92ffaSHans Petter Selasky 
1095d6b92ffaSHans Petter Selasky 	return 0;
1096d6b92ffaSHans Petter Selasky }
1097d6b92ffaSHans Petter Selasky 
osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr)1098d6b92ffaSHans Petter Selasky int osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr)
1099d6b92ffaSHans Petter Selasky {
1100d6b92ffaSHans Petter Selasky 	osm_opensm_t *p_osm;
1101d6b92ffaSHans Petter Selasky 	struct osm_routing_engine *p_routing_eng;
1102d6b92ffaSHans Petter Selasky 	cl_qmap_t *p_sw_guid_tbl;
1103d6b92ffaSHans Petter Selasky 	int failed = 0;
1104d6b92ffaSHans Petter Selasky 
1105d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_mgr->p_log);
1106d6b92ffaSHans Petter Selasky 
1107d6b92ffaSHans Petter Selasky 	p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
1108d6b92ffaSHans Petter Selasky 	p_osm = p_mgr->p_subn->p_osm;
1109d6b92ffaSHans Petter Selasky 	p_routing_eng = p_osm->routing_engine_list;
1110d6b92ffaSHans Petter Selasky 
1111d6b92ffaSHans Petter Selasky 	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
1112d6b92ffaSHans Petter Selasky 
1113d6b92ffaSHans Petter Selasky 	/*
1114d6b92ffaSHans Petter Selasky 	   If there are no switches in the subnet, we are done.
1115d6b92ffaSHans Petter Selasky 	 */
1116d6b92ffaSHans Petter Selasky 	if (cl_qmap_count(p_sw_guid_tbl) == 0 ||
1117d6b92ffaSHans Petter Selasky 	    ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0)
1118d6b92ffaSHans Petter Selasky 		goto Exit;
1119d6b92ffaSHans Petter Selasky 
1120d6b92ffaSHans Petter Selasky 	failed = -1;
1121d6b92ffaSHans Petter Selasky 	p_osm->routing_engine_used = NULL;
1122d6b92ffaSHans Petter Selasky 	while (p_routing_eng) {
1123d6b92ffaSHans Petter Selasky 		failed = ucast_mgr_route(p_routing_eng, p_osm);
1124d6b92ffaSHans Petter Selasky 		if (!failed)
1125d6b92ffaSHans Petter Selasky 			break;
1126d6b92ffaSHans Petter Selasky 		p_routing_eng = p_routing_eng->next;
1127d6b92ffaSHans Petter Selasky 	}
1128d6b92ffaSHans Petter Selasky 
1129d6b92ffaSHans Petter Selasky 	if (!p_osm->routing_engine_used &&
1130d6b92ffaSHans Petter Selasky 	    p_osm->no_fallback_routing_engine != TRUE) {
1131d6b92ffaSHans Petter Selasky 		/* If configured routing algorithm failed, use default MinHop */
1132d6b92ffaSHans Petter Selasky 		failed = ucast_mgr_route(p_osm->default_routing_engine, p_osm);
1133d6b92ffaSHans Petter Selasky 	}
1134d6b92ffaSHans Petter Selasky 
1135d6b92ffaSHans Petter Selasky 	if (p_osm->routing_engine_used) {
1136d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
1137d6b92ffaSHans Petter Selasky 			"%s tables configured on all switches\n",
1138d6b92ffaSHans Petter Selasky 			osm_routing_engine_type_str(p_osm->
1139d6b92ffaSHans Petter Selasky 						    routing_engine_used->type));
1140d6b92ffaSHans Petter Selasky 
1141d6b92ffaSHans Petter Selasky 		if (p_mgr->p_subn->opt.use_ucast_cache)
1142d6b92ffaSHans Petter Selasky 			p_mgr->cache_valid = TRUE;
1143d6b92ffaSHans Petter Selasky 	} else {
1144d6b92ffaSHans Petter Selasky 		p_mgr->p_subn->subnet_initialization_error = TRUE;
1145d6b92ffaSHans Petter Selasky 		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
1146d6b92ffaSHans Petter Selasky 			"No routing engine able to successfully configure "
1147d6b92ffaSHans Petter Selasky 			" switch tables on current fabric\n");
1148d6b92ffaSHans Petter Selasky 	}
1149d6b92ffaSHans Petter Selasky Exit:
1150d6b92ffaSHans Petter Selasky 	CL_PLOCK_RELEASE(p_mgr->p_lock);
1151d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_mgr->p_log);
1152d6b92ffaSHans Petter Selasky 	return failed;
1153d6b92ffaSHans Petter Selasky }
1154d6b92ffaSHans Petter Selasky 
ucast_build_lid_matrices(void * context)1155d6b92ffaSHans Petter Selasky static int ucast_build_lid_matrices(void *context)
1156d6b92ffaSHans Petter Selasky {
1157d6b92ffaSHans Petter Selasky 	return osm_ucast_mgr_build_lid_matrices(context);
1158d6b92ffaSHans Petter Selasky }
1159d6b92ffaSHans Petter Selasky 
ucast_build_lfts(void * context)1160d6b92ffaSHans Petter Selasky static int ucast_build_lfts(void *context)
1161d6b92ffaSHans Petter Selasky {
1162d6b92ffaSHans Petter Selasky 	return ucast_mgr_build_lfts(context);
1163d6b92ffaSHans Petter Selasky }
1164d6b92ffaSHans Petter Selasky 
osm_ucast_minhop_setup(struct osm_routing_engine * r,osm_opensm_t * osm)1165d6b92ffaSHans Petter Selasky int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
1166d6b92ffaSHans Petter Selasky {
1167d6b92ffaSHans Petter Selasky 	r->context = &osm->sm.ucast_mgr;
1168d6b92ffaSHans Petter Selasky 	r->build_lid_matrices = ucast_build_lid_matrices;
1169d6b92ffaSHans Petter Selasky 	r->ucast_build_fwd_tables = ucast_build_lfts;
1170d6b92ffaSHans Petter Selasky 	return 0;
1171d6b92ffaSHans Petter Selasky }
1172d6b92ffaSHans Petter Selasky 
ucast_dor_build_lfts(void * context)1173d6b92ffaSHans Petter Selasky static int ucast_dor_build_lfts(void *context)
1174d6b92ffaSHans Petter Selasky {
1175d6b92ffaSHans Petter Selasky 	osm_ucast_mgr_t *mgr = context;
1176d6b92ffaSHans Petter Selasky 	int ret;
1177d6b92ffaSHans Petter Selasky 
1178d6b92ffaSHans Petter Selasky 	mgr->is_dor = 1;
1179d6b92ffaSHans Petter Selasky 	ret = ucast_mgr_build_lfts(mgr);
1180d6b92ffaSHans Petter Selasky 	mgr->is_dor = 0;
1181d6b92ffaSHans Petter Selasky 
1182d6b92ffaSHans Petter Selasky 	return ret;
1183d6b92ffaSHans Petter Selasky }
1184d6b92ffaSHans Petter Selasky 
osm_ucast_dor_setup(struct osm_routing_engine * r,osm_opensm_t * osm)1185d6b92ffaSHans Petter Selasky int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
1186d6b92ffaSHans Petter Selasky {
1187d6b92ffaSHans Petter Selasky 	r->context = &osm->sm.ucast_mgr;
1188d6b92ffaSHans Petter Selasky 	r->build_lid_matrices = ucast_build_lid_matrices;
1189d6b92ffaSHans Petter Selasky 	r->ucast_build_fwd_tables = ucast_dor_build_lfts;
1190d6b92ffaSHans Petter Selasky 	return 0;
1191d6b92ffaSHans Petter Selasky }
1192d6b92ffaSHans Petter Selasky 
ucast_dummy_build_lid_matrices(void * context)1193d6b92ffaSHans Petter Selasky int ucast_dummy_build_lid_matrices(void *context)
1194d6b92ffaSHans Petter Selasky {
1195d6b92ffaSHans Petter Selasky 	return 0;
1196d6b92ffaSHans Petter Selasky }
1197