split off minhop code into own files out of osm_ucast_mgr.c.
Al
--
Albert Chu
[EMAIL PROTECTED]
925-422-5311
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
>From 319b1855eb777204037b16a8cc07acd94e6a583d Mon Sep 17 00:00:00 2001
From: Albert Chu <[EMAIL PROTECTED]>
Date: Fri, 12 Sep 2008 14:19:15 -0700
Subject: [PATCH] move minhop routing from osm_ucast_mgr to own files
Signed-off-by: Albert Chu <[EMAIL PROTECTED]>
---
opensm/include/opensm/osm_ucast_mgr.h | 23 --
opensm/include/opensm/osm_ucast_minhop.h | 90 +++++
opensm/opensm/Makefile.am | 7 +-
opensm/opensm/osm_ucast_mgr.c | 551 +---------------------------
opensm/opensm/osm_ucast_minhop.c | 605 ++++++++++++++++++++++++++++++
opensm/opensm/osm_ucast_updn.c | 5 +-
6 files changed, 705 insertions(+), 576 deletions(-)
create mode 100644 opensm/include/opensm/osm_ucast_minhop.h
create mode 100644 opensm/opensm/osm_ucast_minhop.c
diff --git a/opensm/include/opensm/osm_ucast_mgr.h b/opensm/include/opensm/osm_ucast_mgr.h
index 1dc9a37..8b9f115 100644
--- a/opensm/include/opensm/osm_ucast_mgr.h
+++ b/opensm/include/opensm/osm_ucast_mgr.h
@@ -255,29 +255,6 @@ osm_ucast_mgr_set_fwd_table(IN osm_ucast_mgr_t * const p_mgr,
* Unicast Manager
*********/
-/****f* OpenSM: Unicast Manager/osm_ucast_mgr_build_lid_matrices
-* NAME
-* osm_ucast_mgr_build_lid_matrices
-*
-* DESCRIPTION
-* Build switches's lid matrices.
-*
-* SYNOPSIS
-*/
-void osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * const p_mgr);
-/*
-* PARAMETERS
-* p_mgr
-* [in] Pointer to an osm_ucast_mgr_t object.
-*
-* NOTES
-* This function processes the subnet, configuring switches'
-* min hops tables (aka lid matrices).
-*
-* SEE ALSO
-* Unicast Manager
-*********/
-
/****f* OpenSM: Unicast Manager/osm_ucast_mgr_process
* NAME
* osm_ucast_mgr_process
diff --git a/opensm/include/opensm/osm_ucast_minhop.h b/opensm/include/opensm/osm_ucast_minhop.h
new file mode 100644
index 0000000..d8029e6
--- /dev/null
+++ b/opensm/include/opensm/osm_ucast_minhop.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_UCAST_MINHOP_H_
+#define _OSM_UCAST_MINHOP_H_
+
+#include <opensm/osm_ucast_mgr.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****f* OpenSM: Unicast Minhop/osm_ucast_minhop_build_lid_matrices
+* NAME
+* osm_ucast_minhop_build_lid_matrices
+*
+* DESCRIPTION
+* Build lid matrices for minhop routing.
+*
+* SYNOPSIS
+*/
+int osm_ucast_minhop_build_lid_matrices(IN osm_ucast_mgr_t * const p_mgr);
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object.
+*
+* NOTES
+* This function builds lid matrices for min hop table calculation.
+*********/
+
+/****f* OpenSM: Unicast Minhop/ucast_minhop_build_fwd_tables
+* NAME
+* osm_ucast_minhop_build_fwd_tables
+*
+* DESCRIPTION
+* Build forwarding tables for minhop routing.
+*
+* SYNOPSIS
+*/
+int osm_ucast_minhop_build_fwd_tables(IN osm_ucast_mgr_t * const p_mgr);
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object.
+*
+* NOTES
+* This function configures switches' min hop tables.
+*********/
+
+END_C_DECLS
+#endif /* _OSM_UCAST_MINHOP_H_ */
diff --git a/opensm/opensm/Makefile.am b/opensm/opensm/Makefile.am
index e95a482..ade35d2 100644
--- a/opensm/opensm/Makefile.am
+++ b/opensm/opensm/Makefile.am
@@ -50,9 +50,9 @@ opensm_SOURCES = main.c osm_console_io.c osm_console.c osm_db_files.c \
osm_sm_mad_ctrl.c osm_sm_state_mgr.c osm_state_mgr.c \
osm_subnet.c osm_sw_info_rcv.c osm_switch.c \
osm_prtn.c osm_prtn_config.c osm_qos.c osm_router.c \
- osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_updn.c \
- osm_ucast_lash.c osm_ucast_file.c osm_ucast_ftree.c \
- osm_vl15intf.c osm_vl_arb_rcv.c \
+ osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_minhop.c \
+ osm_ucast_updn.c osm_ucast_lash.c osm_ucast_file.c \
+ osm_ucast_ftree.c osm_vl15intf.c osm_vl_arb_rcv.c \
st.c osm_perfmgr.c osm_perfmgr_db.c \
osm_event_plugin.c osm_dump.c \
osm_qos_parser_y.y osm_qos_parser_l.l osm_qos_policy.c
@@ -115,6 +115,7 @@ opensminclude_HEADERS = \
$(srcdir)/../include/opensm/osm_subnet.h \
$(srcdir)/../include/opensm/osm_switch.h \
$(srcdir)/../include/opensm/osm_ucast_mgr.h \
+ $(srcdir)/../include/opensm/osm_ucast_minhop.h \
$(srcdir)/../include/opensm/osm_vl15intf.h \
$(top_builddir)/include/opensm/osm_version.h
diff --git a/opensm/opensm/osm_ucast_mgr.c b/opensm/opensm/osm_ucast_mgr.c
index 9d0ad13..2193c15 100644
--- a/opensm/opensm/osm_ucast_mgr.c
+++ b/opensm/opensm/osm_ucast_mgr.c
@@ -51,6 +51,7 @@
#include <complib/cl_debug.h>
#include <complib/cl_qlist.h>
#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_ucast_minhop.h>
#include <opensm/osm_sm.h>
#include <opensm/osm_log.h>
#include <opensm/osm_node.h>
@@ -105,225 +106,6 @@ osm_ucast_mgr_init(IN osm_ucast_mgr_t * const p_mgr, IN osm_sm_t * sm)
}
/**********************************************************************
- Add each switch's own and neighbor LIDs to its LID matrix
-**********************************************************************/
-static void
-__osm_ucast_mgr_process_hop_0_1(IN cl_map_item_t * const p_map_item,
- IN void *context)
-{
- osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
- osm_node_t *p_remote_node;
- uint16_t lid, remote_lid;
- uint8_t i, remote_port;
-
- lid = osm_node_get_base_lid(p_sw->p_node, 0);
- lid = cl_ntoh16(lid);
- osm_switch_set_hops(p_sw, lid, 0, 0);
-
- for (i = 1; i < p_sw->num_ports; i++) {
- p_remote_node =
- osm_node_get_remote_node(p_sw->p_node, i, &remote_port);
-
- if (p_remote_node && p_remote_node->sw &&
- (p_remote_node != p_sw->p_node)) {
- remote_lid = osm_node_get_base_lid(p_remote_node, 0);
- remote_lid = cl_ntoh16(remote_lid);
- osm_switch_set_hops(p_sw, remote_lid, i, 1);
- osm_switch_set_hops(p_remote_node->sw, lid, remote_port,
- 1);
- }
- }
-}
-
-/**********************************************************************
- **********************************************************************/
-static void
-__osm_ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * const p_mgr,
- IN osm_switch_t * const p_this_sw,
- IN osm_switch_t * const p_remote_sw,
- IN const uint8_t port_num,
- IN const uint8_t remote_port_num)
-{
- osm_switch_t *p_sw, *p_next_sw;
- uint16_t lid_ho;
- uint8_t hops;
-
- OSM_LOG_ENTER(p_mgr->p_log);
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Node 0x%" PRIx64 ", remote node 0x%" PRIx64
- ", port 0x%X, remote port 0x%X\n",
- cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
- cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
- port_num, remote_port_num);
-
- p_next_sw = (osm_switch_t *) cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
- while (p_next_sw !=
- (osm_switch_t *) cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl)) {
- p_sw = p_next_sw;
- p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
- lid_ho = osm_node_get_base_lid(p_sw->p_node, 0);
- lid_ho = cl_ntoh16(lid_ho);
- hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
- if (hops == OSM_NO_PATH)
- continue;
- hops++;
- if (hops <
- osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
- if (osm_switch_set_hops
- (p_this_sw, lid_ho, port_num, hops) != 0)
- OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
- "cannot set hops for lid %u at switch 0x%"
- PRIx64 "\n", lid_ho,
- cl_ntoh64(osm_node_get_node_guid
- (p_this_sw->p_node)));
- p_mgr->some_hop_count_set = TRUE;
- }
- }
-
- OSM_LOG_EXIT(p_mgr->p_log);
-}
-
-/**********************************************************************
- **********************************************************************/
-static struct osm_remote_node *
-find_and_add_remote_sys(osm_switch_t *sw, uint8_t port,
- struct osm_remote_guids_count *r)
-{
- unsigned i;
- osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
- osm_node_t *node = p->p_remote_physp->p_node;
-
- for (i = 0; i < r->count; i++)
- if (r->guids[i].node == node)
- return &r->guids[i];
-
- r->guids[i].node = node;
- r->guids[i].forwarded_to = 0;
- r->count++;
- return &r->guids[i];
-}
-
-static void
-__osm_ucast_mgr_process_port(IN osm_ucast_mgr_t * const p_mgr,
- IN osm_switch_t * const p_sw,
- IN osm_port_t * const p_port,
- IN unsigned lid_offset)
-{
- uint16_t min_lid_ho;
- uint16_t max_lid_ho;
- uint16_t lid_ho;
- uint8_t port;
- boolean_t is_ignored_by_port_prof;
- ib_net64_t node_guid;
- struct osm_routing_engine *p_routing_eng;
- unsigned start_from = 1;
-
- OSM_LOG_ENTER(p_mgr->p_log);
-
- osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
-
- /* If the lids are zero - then there was some problem with
- * the initialization. Don't handle this port. */
- if (min_lid_ho == 0 || max_lid_ho == 0) {
- OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
- "Port 0x%" PRIx64 " has LID 0. An initialization "
- "error occurred. Ignoring port\n",
- cl_ntoh64(osm_port_get_guid(p_port)));
- goto Exit;
- }
-
- lid_ho = min_lid_ho + lid_offset;
-
- if (lid_ho > max_lid_ho)
- goto Exit;
-
- if (lid_offset)
- /* ignore potential overflow - it is handled in osm_switch.c */
- start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1) + 1;
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Processing port 0x%" PRIx64 " (\'%s\' port %u), LID %u [%u,%u]\n",
- cl_ntoh64(osm_port_get_guid(p_port)),
- p_port->p_node->print_desc, p_port->p_physp->port_num,
- lid_ho, min_lid_ho, max_lid_ho);
-
- /* TODO - This should be runtime error, not a CL_ASSERT() */
- CL_ASSERT(max_lid_ho < osm_switch_get_fwd_tbl_size(p_sw));
-
- node_guid = osm_node_get_node_guid(p_sw->p_node);
-
- p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine;
-
- /*
- The lid matrix contains the number of hops to each
- lid from each port. From this information we determine
- how best to distribute the LID range across the ports
- that can reach those LIDs.
- */
- port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
- p_mgr->p_subn->ignore_existing_lfts,
- p_mgr->is_dor);
-
- if (port == OSM_NO_PATH) {
- /* do not try to overwrite the ppro of non existing port ... */
- is_ignored_by_port_prof = TRUE;
-
- /* Up/Down routing can cause unreachable routes between some
- switches so we do not report that as an error in that case */
- if (!p_routing_eng->build_lid_matrices) {
- OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A08: "
- "No path to get to LID %u from switch 0x%"
- PRIx64 "\n", lid_ho, cl_ntoh64(node_guid));
- /* trigger a new sweep - try again ... */
- p_mgr->p_subn->subnet_initialization_error = TRUE;
- } else
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "No path to get to LID %u from switch 0x%"
- PRIx64 "\n", lid_ho, cl_ntoh64(node_guid));
- } else {
- osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Routing LID %u to port 0x%X"
- " for switch 0x%" PRIx64 "\n",
- lid_ho, port, cl_ntoh64(node_guid));
-
- /*
- we would like to optionally ignore this port in equalization
- as in the case of the Mellanox Anafa Internal PCI TCA port
- */
- is_ignored_by_port_prof = p->is_prof_ignored;
-
- /*
- We also would ignore this route if the target lid is of
- a switch and the port_profile_switch_node is not TRUE
- */
- if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
- is_ignored_by_port_prof |=
- (osm_node_get_type(p_port->p_node) ==
- IB_NODE_TYPE_SWITCH);
- }
-
- /*
- We have selected the port for this LID.
- Write it to the forwarding tables.
- */
- p_mgr->lft_buf[lid_ho] = port;
- if (!is_ignored_by_port_prof) {
- struct osm_remote_node *rem_node_used;
- osm_switch_count_path(p_sw, port);
- if (port > 0 && p_port->priv &&
- (rem_node_used = find_and_add_remote_sys(p_sw, port,
- p_port->priv)))
- rem_node_used->forwarded_to++;
- }
-
-Exit:
- OSM_LOG_EXIT(p_mgr->p_log);
-}
-
-/**********************************************************************
**********************************************************************/
void
osm_ucast_mgr_set_fwd_table(IN osm_ucast_mgr_t * const p_mgr,
@@ -439,217 +221,6 @@ osm_ucast_mgr_set_fwd_table(IN osm_ucast_mgr_t * const p_mgr,
/**********************************************************************
**********************************************************************/
-static void alloc_ports_priv(osm_ucast_mgr_t *mgr)
-{
- cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
- struct osm_remote_guids_count *r;
- osm_port_t *port;
- cl_map_item_t *item;
- unsigned lmc;
-
- for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
- item = cl_qmap_next(item)) {
- port = (osm_port_t *)item;
- lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
- if (!lmc)
- continue;
- r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
- if (!r) {
- OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
- "cannot allocate memory to track remote"
- " systems for lmc > 0\n");
- port->priv = NULL;
- continue;
- }
- memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
- port->priv = r;
- }
-}
-
-static void free_ports_priv(osm_ucast_mgr_t *mgr)
-{
- cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
- osm_port_t *port;
- cl_map_item_t *item;
- for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
- item = cl_qmap_next(item)) {
- port = (osm_port_t *)item;
- if (port->priv) {
- free(port->priv);
- port->priv = NULL;
- }
- }
-}
-
-static void
-__osm_ucast_mgr_process_tbl(IN cl_map_item_t * const p_map_item,
- IN void *context)
-{
- osm_ucast_mgr_t *p_mgr = context;
- osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
- unsigned i, lids_per_port;
-
- OSM_LOG_ENTER(p_mgr->p_log);
-
- CL_ASSERT(p_sw && p_sw->p_node);
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Processing switch 0x%" PRIx64 "\n",
- cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
-
- /* Initialize LIDs in buffer to invalid port number. */
- memset(p_mgr->lft_buf, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
-
- if (p_mgr->p_subn->opt.lmc)
- alloc_ports_priv(p_mgr);
-
- /*
- Iterate through every port setting LID routes for each
- port based on base LID and LMC value.
- */
- lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
- for (i = 0; i < lids_per_port; i++) {
- cl_qlist_t *list = &p_mgr->port_order_list;
- cl_list_item_t *item;
- for (item = cl_qlist_head(list); item != cl_qlist_end(list);
- item = cl_qlist_next(item)) {
- osm_port_t *port = cl_item_obj(item, port, list_item);
- __osm_ucast_mgr_process_port(p_mgr, p_sw, port, i);
- }
- }
-
- osm_ucast_mgr_set_fwd_table(p_mgr, p_sw);
-
- if (p_mgr->p_subn->opt.lmc)
- free_ports_priv(p_mgr);
-
- OSM_LOG_EXIT(p_mgr->p_log);
-}
-
-/**********************************************************************
- **********************************************************************/
-static void
-__osm_ucast_mgr_process_neighbors(IN cl_map_item_t * const p_map_item,
- IN void *context)
-{
- osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
- osm_ucast_mgr_t *const p_mgr = (osm_ucast_mgr_t *) context;
- osm_node_t *p_node;
- osm_node_t *p_remote_node;
- uint32_t port_num;
- uint8_t remote_port_num;
- uint32_t num_ports;
- osm_physp_t *p_physp;
-
- OSM_LOG_ENTER(p_mgr->p_log);
-
- p_node = p_sw->p_node;
-
- CL_ASSERT(p_node);
- CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Processing switch with GUID 0x%" PRIx64 "\n",
- cl_ntoh64(osm_node_get_node_guid(p_node)));
-
- num_ports = osm_node_get_num_physp(p_node);
-
- /*
- Start with port 1 to skip the switch's management port.
- */
- for (port_num = 1; port_num < num_ports; port_num++) {
- p_remote_node = osm_node_get_remote_node(p_node,
- (uint8_t) port_num,
- &remote_port_num);
-
- if (p_remote_node && p_remote_node->sw
- && (p_remote_node != p_node)) {
- /* make sure the link is healthy. If it is not - don't
- propagate through it. */
- p_physp = osm_node_get_physp_ptr(p_node, port_num);
- if (!p_physp || !osm_link_is_healthy(p_physp))
- continue;
-
- __osm_ucast_mgr_process_neighbor(p_mgr, p_sw,
- p_remote_node->sw,
- (uint8_t) port_num,
- remote_port_num);
-
- }
- }
-
- OSM_LOG_EXIT(p_mgr->p_log);
-}
-
-/**********************************************************************
- **********************************************************************/
-void osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * const p_mgr)
-{
- uint32_t i;
- uint32_t iteration_max;
- cl_qmap_t *p_sw_guid_tbl;
-
- p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
-
- OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
- "Starting switches' Min Hop Table Assignment\n");
-
- /*
- Set the switch matrices for each switch's own port 0 LID(s)
- then set the lid matrices for the each switch's leaf nodes.
- */
- cl_qmap_apply_func(p_sw_guid_tbl,
- __osm_ucast_mgr_process_hop_0_1, p_mgr);
-
- /*
- Get the switch matrices for each switch's neighbors.
- This process requires a number of iterations equal to
- the number of switches in the subnet minus 1.
-
- In each iteration, a switch learns the lid/port/hop
- information (as contained by a switch's lid matrix) from
- its immediate neighbors. After each iteration, a switch
- (and it's neighbors) know more routing information than
- it did on the previous iteration.
- Thus, by repeatedly absorbing the routing information of
- neighbor switches, every switch eventually learns how to
- route all LIDs on the subnet.
-
- Note that there may not be any switches in the subnet if
- we are in simple p2p configuration.
- */
- iteration_max = cl_qmap_count(p_sw_guid_tbl);
-
- /*
- If there are switches in the subnet, iterate until the lid
- matrix has been constructed. Otherwise, just immediately
- indicate we're done if no switches exist.
- */
- if (iteration_max) {
- iteration_max--;
-
- /*
- we need to find out when the propagation of
- hop counts has relaxed. So this global variable
- is preset to 0 on each iteration and if
- if non of the switches was set will exit the
- while loop
- */
- p_mgr->some_hop_count_set = TRUE;
- for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
- i++) {
- p_mgr->some_hop_count_set = FALSE;
- cl_qmap_apply_func(p_sw_guid_tbl,
- __osm_ucast_mgr_process_neighbors,
- p_mgr);
- }
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Min-hop propagated in %d steps\n", i);
- }
-}
-
-/**********************************************************************
- **********************************************************************/
static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
{
osm_switch_t *p_sw;
@@ -674,122 +245,6 @@ static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
/**********************************************************************
**********************************************************************/
-
-static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
-{
- osm_ucast_mgr_t *m = ctx;
- osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
-
- if (!port) {
- OSM_LOG(m->p_log, OSM_LOG_DEBUG,
- "port guid not found: 0x%016" PRIx64 "\n", guid);
- return 0;
- }
-
- if (port->flag) {
- OSM_LOG(m->p_log, OSM_LOG_DEBUG,
- "port guid specified multiple times 0x%016" PRIx64 "\n",
- guid);
- return 0;
- }
-
- cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
- port->flag = 1;
-
- return 0;
-}
-
-static void add_port_to_order_list(cl_map_item_t * const p_map_item, void *ctx)
-{
- osm_port_t *port = (osm_port_t *)p_map_item;
- osm_ucast_mgr_t *m = ctx;
-
- if (!port->flag)
- cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
- else
- port->flag = 0;
-}
-
-static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
-{
- osm_ucast_mgr_t *m = ctx;
- osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
- osm_physp_t *physp;
- unsigned port;
-
- if (!node || !node->sw) {
- OSM_LOG(m->p_log, OSM_LOG_DEBUG,
- "switch with guid 0x%016" PRIx64 " is not found\n",
- guid);
- return 0;
- }
-
- if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
- port >= node->sw->num_ports) {
- OSM_LOG(m->p_log, OSM_LOG_DEBUG,
- "bad port specified for guid 0x%016" PRIx64 "\n", guid);
- return 0;
- }
-
- physp = osm_node_get_physp_ptr(node, port);
- if (!physp)
- return 0;
-
- physp->is_prof_ignored = 1;
-
- return 0;
-}
-
-static void clear_prof_ignore_flag(cl_map_item_t * const p_map_item, void *ctx)
-{
- osm_switch_t *sw = (osm_switch_t *)p_map_item;
- int i;
-
- for (i = 1; i < sw->num_ports; i++) {
- osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
- if (p)
- p->is_prof_ignored = 0;
- }
-}
-
-static void ucast_mgr_build_lfts(osm_ucast_mgr_t *p_mgr)
-{
- cl_qlist_init(&p_mgr->port_order_list);
-
- if (p_mgr->p_subn->opt.guid_routing_order_file) {
- OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
- "Fetching guid routing order file \'%s\'\n",
- p_mgr->p_subn->opt.guid_routing_order_file);
-
- if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
- add_guid_to_order_list, p_mgr))
- OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
- "cannot parse guid routing order file \'%s\'\n",
- p_mgr->p_subn->opt.guid_routing_order_file);
- }
-
- if (p_mgr->p_subn->opt.port_prof_ignore_file) {
- cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
- clear_prof_ignore_flag, NULL);
- if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
- mark_ignored_port, p_mgr)) {
- OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
- "cannot parse port prof ignore file \'%s\'\n",
- p_mgr->p_subn->opt.port_prof_ignore_file);
- }
- }
-
- cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
- add_port_to_order_list, p_mgr);
-
- cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
- __osm_ucast_mgr_process_tbl, p_mgr);
-
- cl_qlist_remove_all(&p_mgr->port_order_list);
-}
-
-/**********************************************************************
- **********************************************************************/
osm_signal_t osm_ucast_mgr_process(IN osm_ucast_mgr_t * const p_mgr)
{
osm_opensm_t *p_osm;
@@ -821,7 +276,7 @@ osm_signal_t osm_ucast_mgr_process(IN osm_ucast_mgr_t * const p_mgr)
if (!p_routing_eng->build_lid_matrices ||
(blm = p_routing_eng->build_lid_matrices(p_routing_eng->context)))
- osm_ucast_mgr_build_lid_matrices(p_mgr);
+ osm_ucast_minhop_build_lid_matrices(p_mgr);
/*
Now that the lid matrices have been built, we can
@@ -830,7 +285,7 @@ osm_signal_t osm_ucast_mgr_process(IN osm_ucast_mgr_t * const p_mgr)
if (!p_routing_eng->ucast_build_fwd_tables ||
(ubft =
p_routing_eng->ucast_build_fwd_tables(p_routing_eng->context)))
- ucast_mgr_build_lfts(p_mgr);
+ osm_ucast_minhop_build_fwd_tables(p_mgr);
/* 'file' routing engine has one unique logic corner case */
if (p_routing_eng->name && (strcmp(p_routing_eng->name, "file") == 0)
diff --git a/opensm/opensm/osm_ucast_minhop.c b/opensm/opensm/osm_ucast_minhop.c
new file mode 100644
index 0000000..4d77dcc
--- /dev/null
+++ b/opensm/opensm/osm_ucast_minhop.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_ucast_minhop.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ Add each switch's own and neighbor LIDs to its LID matrix
+**********************************************************************/
+static void
+__osm_ucast_minhop_process_hop_0_1(IN cl_map_item_t * const p_map_item,
+ IN void *context)
+{
+ osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
+ osm_node_t *p_remote_node;
+ uint16_t lid, remote_lid;
+ uint8_t i, remote_port;
+
+ lid = osm_node_get_base_lid(p_sw->p_node, 0);
+ lid = cl_ntoh16(lid);
+ osm_switch_set_hops(p_sw, lid, 0, 0);
+
+ for (i = 1; i < p_sw->num_ports; i++) {
+ p_remote_node =
+ osm_node_get_remote_node(p_sw->p_node, i, &remote_port);
+
+ if (p_remote_node && p_remote_node->sw &&
+ (p_remote_node != p_sw->p_node)) {
+ remote_lid = osm_node_get_base_lid(p_remote_node, 0);
+ remote_lid = cl_ntoh16(remote_lid);
+ osm_switch_set_hops(p_sw, remote_lid, i, 1);
+ osm_switch_set_hops(p_remote_node->sw, lid, remote_port,
+ 1);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_minhop_process_neighbor(IN osm_ucast_mgr_t * const p_mgr,
+ IN osm_switch_t * const p_this_sw,
+ IN osm_switch_t * const p_remote_sw,
+ IN const uint8_t port_num,
+ IN const uint8_t remote_port_num)
+{
+ osm_switch_t *p_sw, *p_next_sw;
+ uint16_t lid_ho;
+ uint8_t hops;
+
+ OSM_LOG_ENTER(p_mgr->p_log);
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Node 0x%" PRIx64 ", remote node 0x%" PRIx64
+ ", port 0x%X, remote port 0x%X\n",
+ cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
+ cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
+ port_num, remote_port_num);
+
+ p_next_sw = (osm_switch_t *) cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
+ while (p_next_sw !=
+ (osm_switch_t *) cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl)) {
+ p_sw = p_next_sw;
+ p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+ lid_ho = osm_node_get_base_lid(p_sw->p_node, 0);
+ lid_ho = cl_ntoh16(lid_ho);
+ hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
+ if (hops == OSM_NO_PATH)
+ continue;
+ hops++;
+ if (hops <
+ osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
+ if (osm_switch_set_hops
+ (p_this_sw, lid_ho, port_num, hops) != 0)
+ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
+ "cannot set hops for lid %u at switch 0x%"
+ PRIx64 "\n", lid_ho,
+ cl_ntoh64(osm_node_get_node_guid
+ (p_this_sw->p_node)));
+ p_mgr->some_hop_count_set = TRUE;
+ }
+ }
+
+ OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static struct osm_remote_node *
+find_and_add_remote_sys(osm_switch_t *sw, uint8_t port,
+ struct osm_remote_guids_count *r)
+{
+ unsigned i;
+ osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
+ osm_node_t *node = p->p_remote_physp->p_node;
+
+ for (i = 0; i < r->count; i++)
+ if (r->guids[i].node == node)
+ return &r->guids[i];
+
+ r->guids[i].node = node;
+ r->guids[i].forwarded_to = 0;
+ r->count++;
+ return &r->guids[i];
+}
+
+static void
+__osm_ucast_minhop_process_port(IN osm_ucast_mgr_t * const p_mgr,
+ IN osm_switch_t * const p_sw,
+ IN osm_port_t * const p_port,
+ IN unsigned lid_offset)
+{
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint8_t port;
+ boolean_t is_ignored_by_port_prof;
+ ib_net64_t node_guid;
+ struct osm_routing_engine *p_routing_eng;
+ unsigned start_from = 1;
+
+ OSM_LOG_ENTER(p_mgr->p_log);
+
+ osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+ /* If the lids are zero - then there was some problem with
+ * the initialization. Don't handle this port. */
+ if (min_lid_ho == 0 || max_lid_ho == 0) {
+ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
+ "Port 0x%" PRIx64 " has LID 0. An initialization "
+ "error occurred. Ignoring port\n",
+ cl_ntoh64(osm_port_get_guid(p_port)));
+ goto Exit;
+ }
+
+ lid_ho = min_lid_ho + lid_offset;
+
+ if (lid_ho > max_lid_ho)
+ goto Exit;
+
+ if (lid_offset)
+ /* ignore potential overflow - it is handled in osm_switch.c */
+ start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1) + 1;
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Processing port 0x%" PRIx64 " (\'%s\' port %u), LID %u [%u,%u]\n",
+ cl_ntoh64(osm_port_get_guid(p_port)),
+ p_port->p_node->print_desc, p_port->p_physp->port_num,
+ lid_ho, min_lid_ho, max_lid_ho);
+
+ /* TODO - This should be runtime error, not a CL_ASSERT() */
+ CL_ASSERT(max_lid_ho < osm_switch_get_fwd_tbl_size(p_sw));
+
+ node_guid = osm_node_get_node_guid(p_sw->p_node);
+
+ p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine;
+
+ /*
+ The lid matrix contains the number of hops to each
+ lid from each port. From this information we determine
+ how best to distribute the LID range across the ports
+ that can reach those LIDs.
+ */
+ port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
+ p_mgr->p_subn->ignore_existing_lfts,
+ p_mgr->is_dor);
+
+ if (port == OSM_NO_PATH) {
+ /* do not try to overwrite the ppro of non existing port ... */
+ is_ignored_by_port_prof = TRUE;
+
+ /* Up/Down routing can cause unreachable routes between some
+ switches so we do not report that as an error in that case */
+ if (!p_routing_eng->build_lid_matrices) {
+ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A08: "
+ "No path to get to LID %u from switch 0x%"
+ PRIx64 "\n", lid_ho, cl_ntoh64(node_guid));
+ /* trigger a new sweep - try again ... */
+ p_mgr->p_subn->subnet_initialization_error = TRUE;
+ } else
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "No path to get to LID %u from switch 0x%"
+ PRIx64 "\n", lid_ho, cl_ntoh64(node_guid));
+ } else {
+ osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Routing LID %u to port 0x%X"
+ " for switch 0x%" PRIx64 "\n",
+ lid_ho, port, cl_ntoh64(node_guid));
+
+ /*
+ we would like to optionally ignore this port in equalization
+ as in the case of the Mellanox Anafa Internal PCI TCA port
+ */
+ is_ignored_by_port_prof = p->is_prof_ignored;
+
+ /*
+ We also would ignore this route if the target lid is of
+ a switch and the port_profile_switch_node is not TRUE
+ */
+ if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
+ is_ignored_by_port_prof |=
+ (osm_node_get_type(p_port->p_node) ==
+ IB_NODE_TYPE_SWITCH);
+ }
+
+ /*
+ We have selected the port for this LID.
+ Write it to the forwarding tables.
+ */
+ p_mgr->lft_buf[lid_ho] = port;
+ if (!is_ignored_by_port_prof) {
+ struct osm_remote_node *rem_node_used;
+ osm_switch_count_path(p_sw, port);
+ if (port > 0 && p_port->priv &&
+ (rem_node_used = find_and_add_remote_sys(p_sw, port,
+ p_port->priv)))
+ rem_node_used->forwarded_to++;
+ }
+
+Exit:
+ OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void alloc_ports_priv(osm_ucast_mgr_t *mgr)
+{
+ cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
+ struct osm_remote_guids_count *r;
+ osm_port_t *port;
+ cl_map_item_t *item;
+ unsigned lmc;
+
+ for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
+ item = cl_qmap_next(item)) {
+ port = (osm_port_t *)item;
+ lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
+ if (!lmc)
+ continue;
+ r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
+ if (!r) {
+ OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
+ "cannot allocate memory to track remote"
+ " systems for lmc > 0\n");
+ port->priv = NULL;
+ continue;
+ }
+ memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
+ port->priv = r;
+ }
+}
+
+static void free_ports_priv(osm_ucast_mgr_t *mgr)
+{
+ cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
+ osm_port_t *port;
+ cl_map_item_t *item;
+ for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
+ item = cl_qmap_next(item)) {
+ port = (osm_port_t *)item;
+ if (port->priv) {
+ free(port->priv);
+ port->priv = NULL;
+ }
+ }
+}
+
+static void
+__osm_ucast_minhop_process_tbl(IN cl_map_item_t * const p_map_item,
+ IN void *context)
+{
+ osm_ucast_mgr_t *p_mgr = context;
+ osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
+ unsigned i, lids_per_port;
+
+ OSM_LOG_ENTER(p_mgr->p_log);
+
+ CL_ASSERT(p_sw && p_sw->p_node);
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Processing switch 0x%" PRIx64 "\n",
+ cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
+
+ /* Initialize LIDs in buffer to invalid port number. */
+ memset(p_mgr->lft_buf, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+ if (p_mgr->p_subn->opt.lmc)
+ alloc_ports_priv(p_mgr);
+
+ /*
+ Iterate through every port setting LID routes for each
+ port based on base LID and LMC value.
+ */
+ lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
+ for (i = 0; i < lids_per_port; i++) {
+ cl_qlist_t *list = &p_mgr->port_order_list;
+ cl_list_item_t *item;
+ for (item = cl_qlist_head(list); item != cl_qlist_end(list);
+ item = cl_qlist_next(item)) {
+ osm_port_t *port = cl_item_obj(item, port, list_item);
+ __osm_ucast_minhop_process_port(p_mgr, p_sw, port, i);
+ }
+ }
+
+ osm_ucast_mgr_set_fwd_table(p_mgr, p_sw);
+
+ if (p_mgr->p_subn->opt.lmc)
+ free_ports_priv(p_mgr);
+
+ OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_minhop_process_neighbors(IN cl_map_item_t * const p_map_item,
+ IN void *context)
+{
+ osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
+ osm_ucast_mgr_t *const p_mgr = (osm_ucast_mgr_t *) context;
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ uint32_t port_num;
+ uint8_t remote_port_num;
+ uint32_t num_ports;
+ osm_physp_t *p_physp;
+
+ OSM_LOG_ENTER(p_mgr->p_log);
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT(p_node);
+ CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Processing switch with GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+ num_ports = osm_node_get_num_physp(p_node);
+
+ /*
+ Start with port 1 to skip the switch's management port.
+ */
+ for (port_num = 1; port_num < num_ports; port_num++) {
+ p_remote_node = osm_node_get_remote_node(p_node,
+ (uint8_t) port_num,
+ &remote_port_num);
+
+ if (p_remote_node && p_remote_node->sw
+ && (p_remote_node != p_node)) {
+ /* make sure the link is healthy. If it is not - don't
+ propagate through it. */
+ p_physp = osm_node_get_physp_ptr(p_node, port_num);
+ if (!p_physp || !osm_link_is_healthy(p_physp))
+ continue;
+
+ __osm_ucast_minhop_process_neighbor(p_mgr, p_sw,
+ p_remote_node->sw,
+ (uint8_t) port_num,
+ remote_port_num);
+
+ }
+ }
+
+ OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_ucast_minhop_build_lid_matrices(IN osm_ucast_mgr_t * const p_mgr)
+{
+ uint32_t i;
+ uint32_t iteration_max;
+ cl_qmap_t *p_sw_guid_tbl;
+
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
+ "Starting switches' Min Hop Table Assignment\n");
+
+ /*
+ Set the switch matrices for each switch's own port 0 LID(s)
+ then set the lid matrices for the each switch's leaf nodes.
+ */
+ cl_qmap_apply_func(p_sw_guid_tbl,
+ __osm_ucast_minhop_process_hop_0_1, p_mgr);
+
+ /*
+ Get the switch matrices for each switch's neighbors.
+ This process requires a number of iterations equal to
+ the number of switches in the subnet minus 1.
+
+ In each iteration, a switch learns the lid/port/hop
+ information (as contained by a switch's lid matrix) from
+ its immediate neighbors. After each iteration, a switch
+ (and it's neighbors) know more routing information than
+ it did on the previous iteration.
+ Thus, by repeatedly absorbing the routing information of
+ neighbor switches, every switch eventually learns how to
+ route all LIDs on the subnet.
+
+ Note that there may not be any switches in the subnet if
+ we are in simple p2p configuration.
+ */
+ iteration_max = cl_qmap_count(p_sw_guid_tbl);
+
+ /*
+ If there are switches in the subnet, iterate until the lid
+ matrix has been constructed. Otherwise, just immediately
+ indicate we're done if no switches exist.
+ */
+ if (iteration_max) {
+ iteration_max--;
+
+ /*
+ we need to find out when the propagation of
+ hop counts has relaxed. So this global variable
+ is preset to 0 on each iteration and if
+ if non of the switches was set will exit the
+ while loop
+ */
+ p_mgr->some_hop_count_set = TRUE;
+ for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
+ i++) {
+ p_mgr->some_hop_count_set = FALSE;
+ cl_qmap_apply_func(p_sw_guid_tbl,
+ __osm_ucast_minhop_process_neighbors,
+ p_mgr);
+ }
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Min-hop propagated in %d steps\n", i);
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
+{
+ osm_ucast_mgr_t *m = ctx;
+ osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
+
+ if (!port) {
+ OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+ "port guid not found: 0x%016" PRIx64 "\n", guid);
+ return 0;
+ }
+
+ if (port->flag) {
+ OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+ "port guid specified multiple times 0x%016" PRIx64 "\n",
+ guid);
+ return 0;
+ }
+
+ cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
+ port->flag = 1;
+
+ return 0;
+}
+
+static void add_port_to_order_list(cl_map_item_t * const p_map_item, void *ctx)
+{
+ osm_port_t *port = (osm_port_t *)p_map_item;
+ osm_ucast_mgr_t *m = ctx;
+
+ if (!port->flag)
+ cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
+ else
+ port->flag = 0;
+}
+
+static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
+{
+ osm_ucast_mgr_t *m = ctx;
+ osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
+ osm_physp_t *physp;
+ unsigned port;
+
+ if (!node || !node->sw) {
+ OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+ "switch with guid 0x%016" PRIx64 " is not found\n",
+ guid);
+ return 0;
+ }
+
+ if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
+ port >= node->sw->num_ports) {
+ OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+ "bad port specified for guid 0x%016" PRIx64 "\n", guid);
+ return 0;
+ }
+
+ physp = osm_node_get_physp_ptr(node, port);
+ if (!physp)
+ return 0;
+
+ physp->is_prof_ignored = 1;
+
+ return 0;
+}
+
+static void clear_prof_ignore_flag(cl_map_item_t * const p_map_item, void *ctx)
+{
+ osm_switch_t *sw = (osm_switch_t *)p_map_item;
+ int i;
+
+ for (i = 1; i < sw->num_ports; i++) {
+ osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
+ if (p)
+ p->is_prof_ignored = 0;
+ }
+}
+
+int osm_ucast_minhop_build_fwd_tables(osm_ucast_mgr_t * const p_mgr)
+{
+ cl_qlist_init(&p_mgr->port_order_list);
+
+ if (p_mgr->p_subn->opt.guid_routing_order_file) {
+ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+ "Fetching guid routing order file \'%s\'\n",
+ p_mgr->p_subn->opt.guid_routing_order_file);
+
+ if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
+ add_guid_to_order_list, p_mgr))
+ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
+ "cannot parse guid routing order file \'%s\'\n",
+ p_mgr->p_subn->opt.guid_routing_order_file);
+ }
+
+ if (p_mgr->p_subn->opt.port_prof_ignore_file) {
+ cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+ clear_prof_ignore_flag, NULL);
+ if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
+ mark_ignored_port, p_mgr)) {
+ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
+ "cannot parse port prof ignore file \'%s\'\n",
+ p_mgr->p_subn->opt.port_prof_ignore_file);
+ }
+ }
+
+ cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
+ add_port_to_order_list, p_mgr);
+
+ cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+ __osm_ucast_minhop_process_tbl, p_mgr);
+
+ cl_qlist_remove_all(&p_mgr->port_order_list);
+
+ return 0;
+}
diff --git a/opensm/opensm/osm_ucast_updn.c b/opensm/opensm/osm_ucast_updn.c
index 90e9af8..b17f5c1 100644
--- a/opensm/opensm/osm_ucast_updn.c
+++ b/opensm/opensm/osm_ucast_updn.c
@@ -50,6 +50,7 @@
#include <opensm/osm_switch.h>
#include <opensm/osm_opensm.h>
#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_ucast_minhop.h>
/* //////////////////////////// */
/* Local types */
@@ -616,9 +617,9 @@ static int __osm_updn_call(void *ctx)
p_updn->p_osm->subn.opt.root_guid_file);
if (p_updn->p_osm->subn.opt.connect_roots &&
p_updn->num_roots > 1)
- osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
+ osm_ucast_minhop_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
} else {
- osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
+ osm_ucast_minhop_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
updn_find_root_nodes_by_min_hop(p_updn);
}
--
1.5.4.5
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general
To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general