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

Reply via email to