2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_ucast_mgr_t.
39 * This file implements the Unicast Manager object.
44 #endif /* HAVE_CONFIG_H */
49 #include <iba/ib_types.h>
50 #include <complib/cl_qmap.h>
51 #include <complib/cl_debug.h>
52 #include <complib/cl_qlist.h>
53 #include <opensm/osm_ucast_mgr.h>
54 #include <opensm/osm_sm.h>
55 #include <opensm/osm_log.h>
56 #include <opensm/osm_node.h>
57 #include <opensm/osm_switch.h>
58 #include <opensm/osm_helper.h>
59 #include <opensm/osm_msgdef.h>
60 #include <opensm/osm_opensm.h>
62 /**********************************************************************
63 **********************************************************************/
64 void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * const p_mgr)
66 memset(p_mgr, 0, sizeof(*p_mgr));
69 /**********************************************************************
70 **********************************************************************/
71 void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * const p_mgr)
75 OSM_LOG_ENTER(p_mgr->p_log);
77 if (p_mgr->cache_valid)
78 osm_ucast_cache_invalidate(p_mgr);
80 OSM_LOG_EXIT(p_mgr->p_log);
83 /**********************************************************************
84 **********************************************************************/
86 osm_ucast_mgr_init(IN osm_ucast_mgr_t * const p_mgr, IN osm_sm_t * sm)
88 ib_api_status_t status = IB_SUCCESS;
90 OSM_LOG_ENTER(sm->p_log);
92 osm_ucast_mgr_construct(p_mgr);
95 p_mgr->p_log = sm->p_log;
96 p_mgr->p_subn = sm->p_subn;
97 p_mgr->p_lock = sm->p_lock;
99 if (sm->p_subn->opt.use_ucast_cache)
100 cl_qmap_init(&p_mgr->cache_sw_tbl);
102 OSM_LOG_EXIT(p_mgr->p_log);
106 /**********************************************************************
107 Add each switch's own and neighbor LIDs to its LID matrix
108 **********************************************************************/
110 __osm_ucast_mgr_process_hop_0_1(IN cl_map_item_t * const p_map_item,
113 osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
114 osm_node_t *p_remote_node;
115 uint16_t lid, remote_lid;
116 uint8_t i, remote_port;
118 lid = osm_node_get_base_lid(p_sw->p_node, 0);
119 lid = cl_ntoh16(lid);
120 osm_switch_set_hops(p_sw, lid, 0, 0);
122 for (i = 1; i < p_sw->num_ports; i++) {
124 osm_node_get_remote_node(p_sw->p_node, i, &remote_port);
126 if (p_remote_node && p_remote_node->sw &&
127 (p_remote_node != p_sw->p_node)) {
128 remote_lid = osm_node_get_base_lid(p_remote_node, 0);
129 remote_lid = cl_ntoh16(remote_lid);
130 osm_switch_set_hops(p_sw, remote_lid, i, 1);
131 osm_switch_set_hops(p_remote_node->sw, lid, remote_port,
137 /**********************************************************************
138 **********************************************************************/
140 __osm_ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * const p_mgr,
141 IN osm_switch_t * const p_this_sw,
142 IN osm_switch_t * const p_remote_sw,
143 IN const uint8_t port_num,
144 IN const uint8_t remote_port_num)
146 osm_switch_t *p_sw, *p_next_sw;
150 OSM_LOG_ENTER(p_mgr->p_log);
152 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
153 "Node 0x%" PRIx64 ", remote node 0x%" PRIx64
154 ", port %u, remote port %u\n",
155 cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
156 cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
157 port_num, remote_port_num);
159 p_next_sw = (osm_switch_t *) cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
161 (osm_switch_t *) cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl)) {
163 p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
164 lid_ho = osm_node_get_base_lid(p_sw->p_node, 0);
165 lid_ho = cl_ntoh16(lid_ho);
166 hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
167 if (hops == OSM_NO_PATH)
171 osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
172 if (osm_switch_set_hops
173 (p_this_sw, lid_ho, port_num, hops) != 0)
174 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
175 "cannot set hops for lid %u at switch 0x%"
177 cl_ntoh64(osm_node_get_node_guid
178 (p_this_sw->p_node)));
179 p_mgr->some_hop_count_set = TRUE;
183 OSM_LOG_EXIT(p_mgr->p_log);
186 /**********************************************************************
187 **********************************************************************/
188 static struct osm_remote_node *
189 find_and_add_remote_sys(osm_switch_t *sw, uint8_t port,
190 struct osm_remote_guids_count *r)
193 osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
194 osm_node_t *node = p->p_remote_physp->p_node;
196 for (i = 0; i < r->count; i++)
197 if (r->guids[i].node == node)
200 r->guids[i].node = node;
201 r->guids[i].forwarded_to = 0;
207 __osm_ucast_mgr_process_port(IN osm_ucast_mgr_t * const p_mgr,
208 IN osm_switch_t * const p_sw,
209 IN osm_port_t * const p_port,
210 IN unsigned lid_offset)
216 boolean_t is_ignored_by_port_prof;
217 ib_net64_t node_guid;
218 unsigned start_from = 1;
220 OSM_LOG_ENTER(p_mgr->p_log);
222 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
224 /* If the lids are zero - then there was some problem with
225 * the initialization. Don't handle this port. */
226 if (min_lid_ho == 0 || max_lid_ho == 0) {
227 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
228 "Port 0x%" PRIx64 " has LID 0. An initialization "
229 "error occurred. Ignoring port\n",
230 cl_ntoh64(osm_port_get_guid(p_port)));
234 lid_ho = min_lid_ho + lid_offset;
236 if (lid_ho > max_lid_ho)
240 /* ignore potential overflow - it is handled in osm_switch.c */
241 start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1) + 1;
243 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
244 "Processing port 0x%" PRIx64 " (\'%s\' port %u), LID %u [%u,%u]\n",
245 cl_ntoh64(osm_port_get_guid(p_port)),
246 p_port->p_node->print_desc, p_port->p_physp->port_num,
247 lid_ho, min_lid_ho, max_lid_ho);
249 /* TODO - This should be runtime error, not a CL_ASSERT() */
250 CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO);
252 node_guid = osm_node_get_node_guid(p_sw->p_node);
255 The lid matrix contains the number of hops to each
256 lid from each port. From this information we determine
257 how best to distribute the LID range across the ports
258 that can reach those LIDs.
260 port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
261 p_mgr->p_subn->ignore_existing_lfts,
264 if (port == OSM_NO_PATH) {
265 /* do not try to overwrite the ppro of non existing port ... */
266 is_ignored_by_port_prof = TRUE;
268 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
269 "No path to get to LID %u from switch 0x%" PRIx64 "\n",
270 lid_ho, cl_ntoh64(node_guid));
272 osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
274 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
275 "Routing LID %u to port %u"
276 " for switch 0x%" PRIx64 "\n",
277 lid_ho, port, cl_ntoh64(node_guid));
280 we would like to optionally ignore this port in equalization
281 as in the case of the Mellanox Anafa Internal PCI TCA port
283 is_ignored_by_port_prof = p->is_prof_ignored;
286 We also would ignore this route if the target lid is of
287 a switch and the port_profile_switch_node is not TRUE
289 if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
290 is_ignored_by_port_prof |=
291 (osm_node_get_type(p_port->p_node) ==
292 IB_NODE_TYPE_SWITCH);
296 We have selected the port for this LID.
297 Write it to the forwarding tables.
299 p_sw->new_lft[lid_ho] = port;
300 if (!is_ignored_by_port_prof) {
301 struct osm_remote_node *rem_node_used;
302 osm_switch_count_path(p_sw, port);
303 if (port > 0 && p_port->priv &&
304 (rem_node_used = find_and_add_remote_sys(p_sw, port,
306 rem_node_used->forwarded_to++;
310 OSM_LOG_EXIT(p_mgr->p_log);
313 /**********************************************************************
314 **********************************************************************/
315 int osm_ucast_mgr_set_fwd_table(IN osm_ucast_mgr_t * const p_mgr,
316 IN osm_switch_t * const p_sw)
319 osm_dr_path_t *p_path;
320 osm_madw_context_t context;
321 ib_api_status_t status;
323 uint16_t block_id_ho = 0;
324 uint8_t block[IB_SMP_DATA_SIZE];
325 boolean_t set_swinfo_require = FALSE;
331 OSM_LOG_ENTER(p_mgr->p_log);
335 p_node = p_sw->p_node;
339 p_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));
342 Set the top of the unicast forwarding table.
344 si = p_sw->switch_info;
345 lin_top = cl_hton16(p_sw->max_lid_ho);
346 if (lin_top != si.lin_top) {
347 set_swinfo_require = TRUE;
348 si.lin_top = lin_top;
351 /* check to see if the change state bit is on. If it is - then we
353 if (ib_switch_info_get_state_change(&si))
354 life_state = ((p_mgr->p_subn->opt.packet_life_time << 3)
355 | (si.life_state & IB_SWITCH_PSC)) & 0xfc;
357 life_state = (p_mgr->p_subn->opt.packet_life_time << 3) & 0xf8;
359 if ((life_state != si.life_state)
360 || ib_switch_info_get_state_change(&si)) {
361 set_swinfo_require = TRUE;
362 si.life_state = life_state;
365 if (set_swinfo_require) {
366 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
367 "Setting switch FT top to LID %u\n", p_sw->max_lid_ho);
369 context.si_context.light_sweep = FALSE;
370 context.si_context.node_guid = osm_node_get_node_guid(p_node);
371 context.si_context.set_method = TRUE;
373 status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
375 IB_MAD_ATTR_SWITCH_INFO,
376 0, CL_DISP_MSGID_NONE, &context);
378 if (status != IB_SUCCESS)
379 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
380 "Sending SwitchInfo attribute failed (%s)\n",
381 ib_get_err_str(status));
385 Send linear forwarding table blocks to the switch
386 as long as the switch indicates it has blocks needing
390 context.lft_context.node_guid = osm_node_get_node_guid(p_node);
391 context.lft_context.set_method = TRUE;
393 if (!p_sw->new_lft) {
394 /* any routing should provide the new_lft */
395 CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
396 p_mgr->cache_valid && !p_sw->need_update);
400 for (block_id_ho = 0;
401 osm_switch_get_lft_block(p_sw, block_id_ho, block);
403 if (!p_sw->need_update &&
405 p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
409 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
410 "Writing FT block %u\n", block_id_ho);
412 status = osm_req_set(p_mgr->sm, p_path,
413 p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
415 IB_MAD_ATTR_LIN_FWD_TBL,
416 cl_hton32(block_id_ho),
417 CL_DISP_MSGID_NONE, &context);
419 if (status != IB_SUCCESS)
420 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: "
421 "Sending linear fwd. tbl. block failed (%s)\n",
422 ib_get_err_str(status));
426 OSM_LOG_EXIT(p_mgr->p_log);
430 /**********************************************************************
431 **********************************************************************/
432 static void alloc_ports_priv(osm_ucast_mgr_t *mgr)
434 cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
435 struct osm_remote_guids_count *r;
440 for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
441 item = cl_qmap_next(item)) {
442 port = (osm_port_t *)item;
443 lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
446 r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
448 OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
449 "cannot allocate memory to track remote"
450 " systems for lmc > 0\n");
454 memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
459 static void free_ports_priv(osm_ucast_mgr_t *mgr)
461 cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
464 for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
465 item = cl_qmap_next(item)) {
466 port = (osm_port_t *)item;
475 __osm_ucast_mgr_process_tbl(IN cl_map_item_t * const p_map_item,
478 osm_ucast_mgr_t *p_mgr = context;
479 osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
480 unsigned i, lids_per_port;
482 OSM_LOG_ENTER(p_mgr->p_log);
484 CL_ASSERT(p_sw && p_sw->p_node);
486 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
487 "Processing switch 0x%" PRIx64 "\n",
488 cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
490 /* Initialize LIDs in buffer to invalid port number. */
491 memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
493 if (p_mgr->p_subn->opt.lmc)
494 alloc_ports_priv(p_mgr);
497 Iterate through every port setting LID routes for each
498 port based on base LID and LMC value.
500 lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
501 for (i = 0; i < lids_per_port; i++) {
502 cl_qlist_t *list = &p_mgr->port_order_list;
503 cl_list_item_t *item;
504 for (item = cl_qlist_head(list); item != cl_qlist_end(list);
505 item = cl_qlist_next(item)) {
506 osm_port_t *port = cl_item_obj(item, port, list_item);
507 __osm_ucast_mgr_process_port(p_mgr, p_sw, port, i);
511 osm_ucast_mgr_set_fwd_table(p_mgr, p_sw);
513 if (p_mgr->p_subn->opt.lmc)
514 free_ports_priv(p_mgr);
516 OSM_LOG_EXIT(p_mgr->p_log);
519 /**********************************************************************
520 **********************************************************************/
522 __osm_ucast_mgr_process_neighbors(IN cl_map_item_t * const p_map_item,
525 osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
526 osm_ucast_mgr_t *const p_mgr = (osm_ucast_mgr_t *) context;
528 osm_node_t *p_remote_node;
530 uint8_t remote_port_num;
532 osm_physp_t *p_physp;
534 OSM_LOG_ENTER(p_mgr->p_log);
536 p_node = p_sw->p_node;
539 CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
541 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
542 "Processing switch with GUID 0x%" PRIx64 "\n",
543 cl_ntoh64(osm_node_get_node_guid(p_node)));
545 num_ports = osm_node_get_num_physp(p_node);
548 Start with port 1 to skip the switch's management port.
550 for (port_num = 1; port_num < num_ports; port_num++) {
551 p_remote_node = osm_node_get_remote_node(p_node,
555 if (p_remote_node && p_remote_node->sw
556 && (p_remote_node != p_node)) {
557 /* make sure the link is healthy. If it is not - don't
558 propagate through it. */
559 p_physp = osm_node_get_physp_ptr(p_node, port_num);
560 if (!p_physp || !osm_link_is_healthy(p_physp))
563 __osm_ucast_mgr_process_neighbor(p_mgr, p_sw,
571 OSM_LOG_EXIT(p_mgr->p_log);
574 /**********************************************************************
575 **********************************************************************/
576 int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * const p_mgr)
579 uint32_t iteration_max;
580 cl_qmap_t *p_sw_guid_tbl;
582 p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
584 OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
585 "Starting switches' Min Hop Table Assignment\n");
588 Set the switch matrices for each switch's own port 0 LID(s)
589 then set the lid matrices for the each switch's leaf nodes.
591 cl_qmap_apply_func(p_sw_guid_tbl,
592 __osm_ucast_mgr_process_hop_0_1, p_mgr);
595 Get the switch matrices for each switch's neighbors.
596 This process requires a number of iterations equal to
597 the number of switches in the subnet minus 1.
599 In each iteration, a switch learns the lid/port/hop
600 information (as contained by a switch's lid matrix) from
601 its immediate neighbors. After each iteration, a switch
602 (and it's neighbors) know more routing information than
603 it did on the previous iteration.
604 Thus, by repeatedly absorbing the routing information of
605 neighbor switches, every switch eventually learns how to
606 route all LIDs on the subnet.
608 Note that there may not be any switches in the subnet if
609 we are in simple p2p configuration.
611 iteration_max = cl_qmap_count(p_sw_guid_tbl);
614 If there are switches in the subnet, iterate until the lid
615 matrix has been constructed. Otherwise, just immediately
616 indicate we're done if no switches exist.
622 we need to find out when the propagation of
623 hop counts has relaxed. So this global variable
624 is preset to 0 on each iteration and if
625 if non of the switches was set will exit the
628 p_mgr->some_hop_count_set = TRUE;
629 for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
631 p_mgr->some_hop_count_set = FALSE;
632 cl_qmap_apply_func(p_sw_guid_tbl,
633 __osm_ucast_mgr_process_neighbors,
636 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
637 "Min-hop propagated in %d steps\n", i);
643 /**********************************************************************
644 **********************************************************************/
645 static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
650 lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);
651 lids = lids ? lids - 1 : 0;
653 for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
654 p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl);
655 p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
656 if (osm_switch_prepare_path_rebuild(p_sw, lids)) {
657 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: "
658 "cannot setup switch 0x%016" PRIx64 "\n",
659 cl_ntoh64(osm_node_get_node_guid
667 /**********************************************************************
668 **********************************************************************/
670 static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
672 osm_ucast_mgr_t *m = ctx;
673 osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
676 OSM_LOG(m->p_log, OSM_LOG_DEBUG,
677 "port guid not found: 0x%016" PRIx64 "\n", guid);
682 OSM_LOG(m->p_log, OSM_LOG_DEBUG,
683 "port guid specified multiple times 0x%016" PRIx64 "\n",
688 cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
694 static void add_port_to_order_list(cl_map_item_t * const p_map_item, void *ctx)
696 osm_port_t *port = (osm_port_t *)p_map_item;
697 osm_ucast_mgr_t *m = ctx;
700 cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
705 static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
707 osm_ucast_mgr_t *m = ctx;
708 osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
712 if (!node || !node->sw) {
713 OSM_LOG(m->p_log, OSM_LOG_DEBUG,
714 "switch with guid 0x%016" PRIx64 " is not found\n",
719 if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
720 port >= node->sw->num_ports) {
721 OSM_LOG(m->p_log, OSM_LOG_DEBUG,
722 "bad port specified for guid 0x%016" PRIx64 "\n", guid);
726 physp = osm_node_get_physp_ptr(node, port);
730 physp->is_prof_ignored = 1;
735 static void clear_prof_ignore_flag(cl_map_item_t * const p_map_item, void *ctx)
737 osm_switch_t *sw = (osm_switch_t *)p_map_item;
740 for (i = 1; i < sw->num_ports; i++) {
741 osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
743 p->is_prof_ignored = 0;
747 static int ucast_mgr_build_lfts(osm_ucast_mgr_t *p_mgr)
749 cl_qlist_init(&p_mgr->port_order_list);
751 if (p_mgr->p_subn->opt.guid_routing_order_file) {
752 OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
753 "Fetching guid routing order file \'%s\'\n",
754 p_mgr->p_subn->opt.guid_routing_order_file);
756 if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
757 add_guid_to_order_list, p_mgr))
758 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
759 "cannot parse guid routing order file \'%s\'\n",
760 p_mgr->p_subn->opt.guid_routing_order_file);
763 if (p_mgr->p_subn->opt.port_prof_ignore_file) {
764 cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
765 clear_prof_ignore_flag, NULL);
766 if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
767 mark_ignored_port, p_mgr)) {
768 OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
769 "cannot parse port prof ignore file \'%s\'\n",
770 p_mgr->p_subn->opt.port_prof_ignore_file);
774 cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
775 add_port_to_order_list, p_mgr);
777 cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
778 __osm_ucast_mgr_process_tbl, p_mgr);
780 cl_qlist_remove_all(&p_mgr->port_order_list);
785 /**********************************************************************
786 **********************************************************************/
787 static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t *osm)
791 OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
792 "building routing with \'%s\' routing algorithm...\n", r->name);
794 if (!r->build_lid_matrices ||
795 (ret = r->build_lid_matrices(r->context)) > 0)
796 ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr);
799 OSM_LOG(&osm->log, OSM_LOG_ERROR,
800 "%s: cannot build lid matrices.\n", r->name);
804 if (!r->ucast_build_fwd_tables ||
805 (ret = r->ucast_build_fwd_tables(r->context)) > 0)
806 ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr);
809 OSM_LOG(&osm->log, OSM_LOG_ERROR,
810 "%s: cannot build fwd tables.\n", r->name);
814 osm->routing_engine_used = osm_routing_engine_type(r->name);
819 int osm_ucast_mgr_process(IN osm_ucast_mgr_t * const p_mgr)
822 struct osm_routing_engine *p_routing_eng;
823 cl_qmap_t *p_sw_guid_tbl;
825 OSM_LOG_ENTER(p_mgr->p_log);
827 p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
828 p_osm = p_mgr->p_subn->p_osm;
829 p_routing_eng = p_osm->routing_engine_list;
831 CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
834 If there are no switches in the subnet, we are done.
836 if (cl_qmap_count(p_sw_guid_tbl) == 0 ||
837 ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0)
840 p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_NONE;
841 while (p_routing_eng) {
842 if (!ucast_mgr_route(p_routing_eng, p_osm))
844 p_routing_eng = p_routing_eng->next;
847 if (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_NONE) {
848 /* If configured routing algorithm failed, use default MinHop */
849 osm_ucast_mgr_build_lid_matrices(p_mgr);
850 ucast_mgr_build_lfts(p_mgr);
851 p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_MINHOP;
854 OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
855 "%s tables configured on all switches\n",
856 osm_routing_engine_type_str(p_osm->routing_engine_used));
858 if (p_mgr->p_subn->opt.use_ucast_cache)
859 p_mgr->cache_valid = TRUE;
862 CL_PLOCK_RELEASE(p_mgr->p_lock);
863 OSM_LOG_EXIT(p_mgr->p_log);
867 static int ucast_build_lid_matrices(void *context)
869 return osm_ucast_mgr_build_lid_matrices(context);
872 static int ucast_build_lfts(void *context)
874 return ucast_mgr_build_lfts(context);
877 int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
879 r->context = &osm->sm.ucast_mgr;
880 r->build_lid_matrices = ucast_build_lid_matrices;
881 r->ucast_build_fwd_tables = ucast_build_lfts;
885 static int ucast_dor_build_lfts(void *context)
887 osm_ucast_mgr_t *mgr = context;
891 ret = ucast_mgr_build_lfts(mgr);
897 int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
899 r->context = &osm->sm.ucast_mgr;
900 r->build_lid_matrices = ucast_build_lid_matrices;
901 r->ucast_build_fwd_tables = ucast_dor_build_lfts;