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