[ofa-general] [PATCH] opensm: Reduce heap consumption by unicast routing tables (LFTs)

Hal Rosenstock hnrose at comcast.net
Sat Aug 29 08:30:10 PDT 2009


Heap memory consumption by the unicast and multicast routing tables can be
reduced.

Using valgrind --tool=massif (for heap profiling), there are couple of places that consume most of the heap memory:
->38.75% (11,206,656B) 0x43267E: osm_switch_new (osm_switch.c:134)
->12.89% (3,728,256B) 0x40F8C9: osm_mcast_tbl_init (osm_mcast_tbl.c:96)

osm_switch_new (osm_switch.c:108):
       p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);

>From ib_types.h
 #define IB_LID_UCAST_END_HO 0xBFFF

The LFT can be allocated in smaller chunks. If there is a LID that
exeeds the current LFT size, LFT is reallocated with an increased size.
This reduces performance and increases memory fragmentation, so this
tradeoff is made optional based on new build and config options (see below).

Using a 4K chunk as the minimal LFT block reduces the memory used
by the LFTs by a factor of 12. For a larger (than 4K) fabric, 4K is added each
time the existing LFT size is insufficient.

So it looks like for cluster of 2-4K withan LMC of 0 about 40% (!!!) of the
heap memory can be saved:

 - 39% used by LFTs, each with 48K entries - SM can allocate 4K entries instead.

There is a new build option to specify whether to include the FT heap optimization code or not. It defaults to off and not include the new code (basically just the code that exists today).

A new config option specifies whether to optimize FT allocation and
defaults to off.
Another new config option will specify the LFT allocation chunk and
defaults to 4K.
These chunks will be used as the initial minimum allocation and increased
in increments of the chunk using realloc.

LFTs are only be increased in size and are never reduced in size. If a realloc for an LFT fails, it results in an exit.

A similar subsequent change will do this for MFTs.

Signed-off-by: Hal Rosenstock <hal.rosenstock at gmail.com>
---
diff --git a/opensm/config/osmvsel.m4 b/opensm/config/osmvsel.m4
index c24930b..1c7c8a2 100644
--- a/opensm/config/osmvsel.m4
+++ b/opensm/config/osmvsel.m4
@@ -232,6 +232,25 @@ fi
 # --- END OPENIB_OSM_PERF_MGR_SEL ---
 ]) dnl OPENIB_OSM_PERF_MGR_SEL
 
+dnl Check if they want the FT heap optimization 
+AC_DEFUN([OPENIB_OSM_FT_OPTIMIZE_HEAP_SEL], [
+# --- BEGIN OPENIB_OSM_FT_OPTIMIZE_HEAP_SEL ---
+
+dnl enable the FT heap optimization
+AC_ARG_ENABLE(ft-heap-optimize,
+[  --enable-ft-heap-optimize Enable FT heap optimization (default no)],
+   [case $enableval in
+     yes) ft_heap_optimize=yes ;;
+     no)  ft_heap_optimize=no ;;
+   esac],
+   ft_heap_optimize=no)
+if test $ft_heap_optimize = yes; then
+  AC_DEFINE(ENABLE_OSM_FT_HEAP_OPTIMIZATION,
+	1,
+	[Define as 1 if you want to enable the FT heap optimization])
+fi
+# --- END OPENIB_OSM_FT_OPTIMIZE_HEAP_SEL ---
+]) dnl OPENIB_OSM_FT_OPTIMIZE_HEAP_SEL
 
 dnl Check if they want the event plugin
 AC_DEFUN([OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL], [
diff --git a/opensm/configure.in b/opensm/configure.in
index 8a6b4c0..9b5ec00 100644
--- a/opensm/configure.in
+++ b/opensm/configure.in
@@ -87,6 +87,9 @@ OPENIB_OSM_CONSOLE_SOCKET_SEL
 dnl select performance manager or not
 OPENIB_OSM_PERF_MGR_SEL
 
+dnl select FT heap optimization or not
+OPENIB_OSM_FT_OPTIMIZE_HEAP_SEL
+
 dnl resolve <sysconfdir> config dir.
 conf_dir_tmp1="`eval echo ${sysconfdir} | sed 's/^NONE/$ac_default_prefix/'`"
 SYS_CONFIG_DIR="`eval echo $conf_dir_tmp1`"
diff --git a/opensm/include/opensm/osm_base.h b/opensm/include/opensm/osm_base.h
index 0537002..89b125c 100644
--- a/opensm/include/opensm/osm_base.h
+++ b/opensm/include/opensm/osm_base.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
  *
@@ -449,6 +449,18 @@ BEGIN_C_DECLS
 */
 #define OSM_DEFAULT_SMP_MAX_ON_WIRE 4
 /***********/
+/****d* OpenSM: Base/OSM_DEFAULT_LFT_CHUNKS
+* NAME
+*	OSM_DEFAULT_LFT_CHUNKS
+*
+* DESCRIPTION
+*	Specifies the default number of 64 entry (byte) chunks in LFT
+*	related memory (re)allocation. Default is 64 (4K bytes).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LFT_CHUNKS 64
+/***********/
 /****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
 * NAME
 *	OSM_SM_DEFAULT_QP0_RCV_SIZE
diff --git a/opensm/include/opensm/osm_subnet.h b/opensm/include/opensm/osm_subnet.h
index 6c20de8..be90ce4 100644
--- a/opensm/include/opensm/osm_subnet.h
+++ b/opensm/include/opensm/osm_subnet.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
@@ -218,6 +218,10 @@ typedef struct osm_subn_opt {
 	uint32_t perfmgr_max_outstanding_queries;
 	char *event_db_dump_file;
 #endif				/* ENABLE_OSM_PERF_MGR */
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	boolean_t ft_heap_optimization;
+	uint32_t lft_chunks;
+#endif				/* ENABLE_OSM_FT_HEAP_OPTIMIZATION */
 	char *event_plugin_name;
 	char *node_name_map_name;
 	char *prefix_routes_file;
@@ -437,6 +441,12 @@ typedef struct osm_subn_opt {
 *	perfmgr_sweep_time_s
 *		Define the period (in seconds) of PerfMgr sweeps
 *
+*	ft_heap_optimization
+*		Enable or disable forwarding table (FT) heap optimization
+*
+*	lft_chunks
+*		Number of 64 entry (byte) chunks used in LFT (re)allocation
+*
 *       event_db_dump_file
 *               File to dump the event database to
 *
diff --git a/opensm/include/opensm/osm_switch.h b/opensm/include/opensm/osm_switch.h
index 7ce28c5..2c60fb6 100644
--- a/opensm/include/opensm/osm_switch.h
+++ b/opensm/include/opensm/osm_switch.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 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
@@ -102,6 +102,8 @@ typedef struct osm_switch {
 	osm_port_profile_t *p_prof;
 	uint8_t *lft;
 	uint8_t *new_lft;
+	uint16_t lft_size;
+	uint16_t new_lft_size;
 	osm_mcast_tbl_t mcast_tbl;
 	unsigned endport_links;
 	unsigned need_update;
@@ -219,7 +221,8 @@ void osm_switch_delete(IN OUT osm_switch_t ** const pp_sw);
 * SYNOPSIS
 */
 osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
-			     IN const osm_madw_t * const p_madw);
+			     IN const osm_madw_t * const p_madw,
+			     IN osm_subn_t * const p_subn);
 /*
 * PARAMETERS
 *	p_node
@@ -227,7 +230,10 @@ osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
 *
 *	p_madw
 *		[in] Pointer to the MAD Wrapper containing the switch's
-*		SwitchInfo attribute.
+*		SwitchInfo attribute
+*
+*	p_subn
+*		[in] Pointer to the subnet object
 *
 * RETURN VALUES
 *	Pointer to the new initialized switch object.
@@ -408,7 +414,7 @@ static inline uint8_t
 osm_switch_get_port_by_lid(IN const osm_switch_t * const p_sw,
 			   IN const uint16_t lid_ho)
 {
-	if (lid_ho == 0 || lid_ho > IB_LID_UCAST_END_HO)
+	if (lid_ho == 0 || lid_ho >= p_sw->lft_size)
 		return OSM_NO_PATH;
 	return p_sw->lft[lid_ho];
 }
@@ -575,6 +581,44 @@ osm_switch_get_max_block_id_in_use(IN const osm_switch_t * const p_sw)
 *	Switch object
 *********/
 
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+/****f* OpenSM: Switch/osm_switch_set_new_lft_entry
+* NAME
+*	osm_switch_set_new_lft_entry
+*
+* DESCRIPTION
+*	Set a LID entry in the switch's new_lft.
+*
+* SYNOPSIS
+*
+*/
+boolean_t
+osm_switch_set_new_lft_entry(IN osm_switch_t * const p_sw,
+			     IN uint16_t lid, IN uint8_t port,
+			     IN const osm_subn_t * const p_subn);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to an osm_switch_t object.
+*
+*	lid
+*		[in] LID.
+*
+*	port
+*		[in] port number.
+*
+*	p_subn
+*		[in] Pointer to an osm_subn_t object.
+*
+* RETURN VALUES
+*	TRUE if success and FALSE if failure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+#endif
+
 /****f* OpenSM: Switch/osm_switch_get_lft_block
 * NAME
 *	osm_switch_get_lft_block
@@ -586,6 +630,7 @@ osm_switch_get_max_block_id_in_use(IN const osm_switch_t * const p_sw)
 */
 boolean_t
 osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
+			 IN const osm_subn_t * const p_subn,
 			 IN const uint16_t block_id,
 			 OUT uint8_t * const p_block);
 /*
@@ -593,6 +638,9 @@ osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
 *	p_sw
 *		[in] Pointer to an osm_switch_t object.
 *
+*	p_subn
+*		[in] Pointer to an osm_subn_t object.
+*
 *	block_ID
 *		[in] The block_id to retrieve.
 *
@@ -714,16 +762,40 @@ osm_switch_count_path(IN osm_switch_t * const p_sw, IN const uint8_t port)
 static inline ib_api_status_t
 osm_switch_set_lft_block(IN osm_switch_t * const p_sw,
 			 IN const uint8_t * const p_block,
-			 IN const uint32_t block_num)
+			 IN const uint32_t block_num,
+			 IN osm_subn_t * const p_subn)
 {
 	uint16_t lid_start =
 		(uint16_t) (block_num * IB_SMP_DATA_SIZE);
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	uint8_t *lft;
+	size_t size;
+#endif
+
 	CL_ASSERT(p_sw);
 
 	if (lid_start + IB_SMP_DATA_SIZE > IB_LID_UCAST_END_HO)
 		return IB_INVALID_PARAMETER;
 
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 	memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
+#else
+	if (!p_subn->opt.ft_heap_optimization)
+		memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
+	else {
+		if (lid_start + IB_SMP_DATA_SIZE > p_sw->lft_size) {
+			size = (lid_start + (1 + p_subn->opt.lft_chunks) * IB_SMP_DATA_SIZE - 1) / IB_SMP_DATA_SIZE * IB_SMP_DATA_SIZE;
+			lft = realloc(p_sw->lft, size);
+			if (!lft)
+				return IB_INSUFFICIENT_MEMORY;
+			memset(lft + p_sw->lft_size, OSM_NO_PATH,
+			       size - p_sw->lft_size);
+			p_sw->lft = lft;
+			p_sw->lft_size = size;
+		}
+		memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
+	}
+#endif
 	return IB_SUCCESS;
 }
 /*
@@ -735,7 +807,10 @@ osm_switch_set_lft_block(IN osm_switch_t * const p_sw,
 *		[in] Pointer to the forwarding table block.
 *
 *	block_num
-*		[in] Block number for this block
+*		[in] Block number for this block.
+*
+*	p_subn
+*		[in] Pointer to the subnet object.
 *
 * RETURN VALUE
 *	None.
diff --git a/opensm/opensm.spec.in b/opensm/opensm.spec.in
index c541804..e1fb073 100644
--- a/opensm/opensm.spec.in
+++ b/opensm/opensm.spec.in
@@ -21,6 +21,13 @@
 %define _disable_event_plugin --disable-default-event-plugin
 %endif
 
+%if %{?_with_ft_heap_optimize:1}%{!?_with_ft_heap_optimize:0}
+%define _enable_ft_heap_optimize --enable-ft-heap-optimize
+%endif
+%if %{?_without_ft_heap_optimize:1}%{!?_without_ft_heap_optimize:0}
+%define _disable_ft_heap_optimize --disable-ft-heap-optimize
+%endif
+
 %if %{?_with_node_name_map:1}%{!?_with_node_name_map:0}
 %define _enable_node_name_map --with-node-name-map%{?_with_node_name_map}
 %endif
@@ -83,6 +90,8 @@ Static version of the opensm libraries
         %{?_disable_console_socket} \
         %{?_enable_perf_mgr} \
         %{?_disable_perf_mgr} \
+        %{?_enable_ft_heap_optimize} \
+        %{?_disable_ft_heap_optimize} \
         %{?_enable_event_plugin} \
         %{?_disable_event_plugin} \
         %{?_enable_node_name_map}
diff --git a/opensm/opensm/osm_lin_fwd_rcv.c b/opensm/opensm/osm_lin_fwd_rcv.c
index ae40b0d..6f05bd7 100644
--- a/opensm/opensm/osm_lin_fwd_rcv.c
+++ b/opensm/opensm/osm_lin_fwd_rcv.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 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
@@ -87,7 +87,8 @@ void osm_lft_rcv_process(IN void *context, IN void *data)
 			"LFT received for nonexistent node "
 			"0x%" PRIx64 "\n", cl_ntoh64(node_guid));
 	} else {
-		status = osm_switch_set_lft_block(p_sw, p_block, block_num);
+		status = osm_switch_set_lft_block(p_sw, p_block, block_num,
+						  sm->p_subn);
 		if (status != IB_SUCCESS) {
 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0402: "
 				"Setting forwarding table block failed (%s)"
diff --git a/opensm/opensm/osm_sa_lft_record.c b/opensm/opensm/osm_sa_lft_record.c
index d092129..b84bf6c 100644
--- a/opensm/opensm/osm_sa_lft_record.c
+++ b/opensm/opensm/osm_sa_lft_record.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 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
@@ -99,7 +99,7 @@ static ib_api_status_t lftr_rcv_new_lftr(IN osm_sa_t * sa,
 	p_rec_item->rec.block_num = cl_hton16(block);
 
 	/* copy the lft block */
-	osm_switch_get_lft_block(p_sw, block, p_rec_item->rec.lft);
+	osm_switch_get_lft_block(p_sw, sa->p_subn, block, p_rec_item->rec.lft);
 
 	cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
 
diff --git a/opensm/opensm/osm_state_mgr.c b/opensm/opensm/osm_state_mgr.c
index 185c700..1423c11 100644
--- a/opensm/opensm/osm_state_mgr.c
+++ b/opensm/opensm/osm_state_mgr.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2009 HNR Consulting. All rights reserved.
  *
@@ -1011,7 +1011,8 @@ static void cleanup_switch(cl_map_item_t * item, void *log)
 	if (!sw->new_lft)
 		return;
 
-	if (memcmp(sw->lft, sw->new_lft, IB_LID_UCAST_END_HO + 1))
+	if (sw->new_lft_size != sw->lft_size ||
+	    memcmp(sw->lft, sw->new_lft, sw->lft_size))
 		osm_log(log, OSM_LOG_ERROR, "ERR 331D: "
 			"LFT of switch 0x%016" PRIx64 " is not up to date.\n",
 			cl_ntoh64(sw->p_node->node_info.node_guid));
diff --git a/opensm/opensm/osm_subnet.c b/opensm/opensm/osm_subnet.c
index 8d63a75..5189229 100644
--- a/opensm/opensm/osm_subnet.c
+++ b/opensm/opensm/osm_subnet.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
@@ -359,6 +359,10 @@ static const opt_rec_t opt_tbl[] = {
 	{ "perfmgr_max_outstanding_queries", OPT_OFFSET(perfmgr_max_outstanding_queries), opts_parse_uint32, NULL, 0 },
 	{ "event_db_dump_file", OPT_OFFSET(event_db_dump_file), opts_parse_charp, NULL, 0 },
 #endif				/* ENABLE_OSM_PERF_MGR */
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	{ "ft_heap_optimization", OPT_OFFSET(ft_heap_optimization), opts_parse_boolean, NULL, 0 },
+	{ "lft_chunks", OPT_OFFSET(lft_chunks), opts_parse_uint32, NULL, 1 },
+#endif				/* ENABLE_OSM_FT_HEAP_OPTIMIZATION */
 	{ "event_plugin_name", OPT_OFFSET(event_plugin_name), opts_parse_charp, NULL, 0 },
 	{ "node_name_map_name", OPT_OFFSET(node_name_map_name), opts_parse_charp, NULL, 0 },
 	{ "qos_max_vls", OPT_OFFSET(qos_options.max_vls), opts_parse_uint32, NULL, 1 },
@@ -723,6 +727,10 @@ void osm_subn_set_default_opt(IN osm_subn_opt_t * const p_opt)
 	    OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
 	p_opt->event_db_dump_file = NULL; /* use default */
 #endif				/* ENABLE_OSM_PERF_MGR */
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	p_opt->ft_heap_optimization = FALSE;
+	p_opt->lft_chunks = OSM_DEFAULT_LFT_CHUNKS;
+#endif				/* ENABLE_OSM_FT_HEAP_OPTIMIZATION */
 
 	p_opt->event_plugin_name = NULL;
 	p_opt->node_name_map_name = NULL;
@@ -1141,6 +1149,18 @@ int osm_subn_verify_config(IN osm_subn_opt_t * const p_opts)
 	}
 #endif
 
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	if (p_opts->ft_heap_optimization) {
+		if (p_opts->lft_chunks < 1 || p_opts->lft_chunks > 768) {
+			log_report(" Invalid Cached Option Value:"
+				   "lft_chunks = %u"
+				   " Using Default:%u\n",
+				   p_opts->lft_chunks, OSM_DEFAULT_LFT_CHUNKS);
+			p_opts->lft_chunks = OSM_DEFAULT_LFT_CHUNKS;
+		}
+	}
+#endif
+
 	return 0;
 }
 
@@ -1465,6 +1485,21 @@ int osm_subn_output_conf(FILE *out, IN osm_subn_opt_t *const p_opts)
 		"# SA database file name\nsa_db_file %s\n\n",
 		p_opts->sa_db_file ? p_opts->sa_db_file : null_str);
 
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	fprintf(out,
+		"# Forwarding table (LFT) heap optimization\n"
+		"ft_heap_optimization %s\n\n",
+		p_opts->ft_heap_optimization ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"# Number of 64 entry (byte) chunks used when (re)allocating "
+		"LFTs\n"
+		"# Values go from 1 (highest granularity) to 786 "
+		"(allocate all the LFT in a single chunk)\n"
+		"lft_chunks %d\n\n",
+		p_opts->lft_chunks);
+#endif				/* ENABLE_OSM_FT_HEAP_OPTIMIZATION */
+
 	fprintf(out,
 		"#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
 		"# SM priority used for deciding who is the master\n"
diff --git a/opensm/opensm/osm_sw_info_rcv.c b/opensm/opensm/osm_sw_info_rcv.c
index c335263..9861525 100644
--- a/opensm/opensm/osm_sw_info_rcv.c
+++ b/opensm/opensm/osm_sw_info_rcv.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 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
@@ -211,7 +211,7 @@ static void si_rcv_process_new(IN osm_sm_t * sm, IN osm_node_t * p_node,
 
 	osm_dump_switch_info(sm->p_log, p_si, OSM_LOG_DEBUG);
 
-	p_sw = osm_switch_new(p_node, p_madw);
+	p_sw = osm_switch_new(p_node, p_madw, sm->p_subn);
 	if (p_sw == NULL) {
 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3608: "
 			"Unable to allocate new switch object\n");
diff --git a/opensm/opensm/osm_switch.c b/opensm/opensm/osm_switch.c
index ce1ca63..0d725e8 100644
--- a/opensm/opensm/osm_switch.c
+++ b/opensm/opensm/osm_switch.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2009 HNR Consulting. All rights reserved.
  *
@@ -51,6 +51,11 @@
 #include <iba/ib_types.h>
 #include <opensm/osm_switch.h>
 
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+static uint8_t no_path_block[IB_SMP_DATA_SIZE] =
+				{[0 ... IB_SMP_DATA_SIZE-1] = OSM_NO_PATH };
+#endif
+
 /**********************************************************************
  **********************************************************************/
 cl_status_t
@@ -101,7 +106,8 @@ void osm_switch_delete(IN OUT osm_switch_t ** const pp_sw)
 /**********************************************************************
  **********************************************************************/
 osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
-			     IN const osm_madw_t * const p_madw)
+			     IN const osm_madw_t * const p_madw,
+			     IN osm_subn_t * const p_subn)
 {
 	osm_switch_t *p_sw;
 	ib_switch_info_t *p_si;
@@ -132,11 +138,22 @@ osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
 	p_sw->num_ports = num_ports;
 	p_sw->need_update = 2;
 
-	p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+	p_sw->lft_size = IB_LID_UCAST_END_HO + 1;
+#else
+	if (!p_subn->opt.ft_heap_optimization)
+		p_sw->lft_size = IB_LID_UCAST_END_HO + 1;
+	else
+		p_sw->lft_size = p_subn->opt.lft_chunks * IB_SMP_DATA_SIZE;
+#endif
+
+	p_sw->lft = malloc(p_sw->lft_size);
 	if (!p_sw->lft)
 		goto err;
 
-	memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+	memset(p_sw->lft, OSM_NO_PATH, p_sw->lft_size);
+
+	p_sw->new_lft_size = p_sw->lft_size;
 
 	p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports);
 	if (!p_sw->p_prof)
@@ -158,10 +175,43 @@ err:
 	return NULL;
 }
 
+#ifdef ENABLE_OSM_FT_HEAP_OPTIMIZATION
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_switch_set_new_lft_entry(IN osm_switch_t * const p_sw,
+			     IN uint16_t lid, IN uint8_t port,
+			     IN const osm_subn_t * const p_subn)
+{
+	size_t size;
+	uint8_t *new_lft;
+
+	if (!p_subn->opt.ft_heap_optimization)
+		p_sw->new_lft[lid] = port;
+	else {
+		if (lid >= p_sw->new_lft_size) {
+			size = (lid + p_subn->opt.lft_chunks * IB_SMP_DATA_SIZE - 1) / IB_SMP_DATA_SIZE * IB_SMP_DATA_SIZE;
+			if (size == p_sw->new_lft_size)
+				size += p_subn->opt.lft_chunks * IB_SMP_DATA_SIZE;
+			new_lft = realloc(p_sw->new_lft, size);
+			if (!new_lft)
+				return FALSE;
+			memset(new_lft + p_sw->new_lft_size, OSM_NO_PATH,
+			       size - p_sw->new_lft_size);
+			p_sw->new_lft = new_lft;
+			p_sw->new_lft_size = size;
+		}
+		p_sw->new_lft[lid] = port;
+	}
+	return TRUE;
+}
+#endif
+
 /**********************************************************************
  **********************************************************************/
 boolean_t
 osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
+			 IN const osm_subn_t * const p_subn,
 			 IN const uint16_t block_id,
 			 OUT uint8_t * const p_block)
 {
@@ -174,7 +224,19 @@ osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
 		return FALSE;
 
 	CL_ASSERT(base_lid_ho + IB_SMP_DATA_SIZE <= IB_LID_UCAST_END_HO);
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 	memcpy(p_block, &(p_sw->lft[base_lid_ho]), IB_SMP_DATA_SIZE);
+#else
+	if (!p_subn->opt.ft_heap_optimization)
+		memcpy(p_block, &(p_sw->lft[base_lid_ho]), IB_SMP_DATA_SIZE);
+	else {
+		if (base_lid_ho + IB_SMP_DATA_SIZE > p_sw->lft_size)
+			memcpy(p_block, &no_path_block[0], IB_SMP_DATA_SIZE);
+		else
+			memcpy(p_block, &(p_sw->lft[base_lid_ho]),
+			       IB_SMP_DATA_SIZE);
+	}
+#endif
 	return TRUE;
 }
 
@@ -517,10 +579,10 @@ osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids)
 	osm_switch_clear_hops(p_sw);
 
 	if (!p_sw->new_lft &&
-	    !(p_sw->new_lft = malloc(IB_LID_UCAST_END_HO + 1)))
+	    !(p_sw->new_lft = malloc(p_sw->new_lft_size)))
 		return IB_INSUFFICIENT_MEMORY;
 
-	memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+	memset(p_sw->new_lft, OSM_NO_PATH, p_sw->new_lft_size);
 
 	if (!p_sw->hops) {
 		hops = malloc((max_lids + 1) * sizeof(hops[0]));
diff --git a/opensm/opensm/osm_ucast_cache.c b/opensm/opensm/osm_ucast_cache.c
index 30a3c1d..73f1ce0 100644
--- a/opensm/opensm/osm_ucast_cache.c
+++ b/opensm/opensm/osm_ucast_cache.c
@@ -73,6 +73,7 @@ typedef struct cache_switch {
 	uint16_t num_hops;
 	uint8_t **hops;
 	uint8_t *lft;
+	uint16_t lft_size;
 	uint8_t num_ports;
 	cache_port_t ports[0];
 } cache_switch_t;
@@ -349,6 +350,7 @@ cache_restore_ucast_info(osm_ucast_mgr_t * p_mgr,
 	if (p_sw->new_lft)
 		free(p_sw->new_lft);
 	p_sw->new_lft = p_cache_sw->lft;
+	p_sw->new_lft_size = p_cache_sw->lft_size;
 	p_cache_sw->lft = NULL;
 
 	p_sw->num_hops = p_cache_sw->num_hops;
@@ -1023,10 +1025,12 @@ void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node)
 			/* LFT buffer exists - we use it, because
 			   it is more updated than the switch's LFT */
 			p_cache_sw->lft = p_node->sw->new_lft;
+			p_cache_sw->lft_size = p_node->sw->new_lft_size;
 			p_node->sw->new_lft = NULL;
 		} else {
 			/* no LFT buffer, so we use the switch's LFT */
 			p_cache_sw->lft = p_node->sw->lft;
+			p_cache_sw->lft_size = p_node->sw->lft_size;
 			p_node->sw->lft = NULL;
 		}
 		p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho;
@@ -1079,10 +1083,11 @@ int osm_ucast_cache_process(osm_ucast_mgr_t * p_mgr)
 			/* no new routing was recently calculated for this
 			   switch, but the LFT needs to be updated anyway */
 			p_sw->new_lft = p_sw->lft;
-			p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);
+			p_sw->new_lft_size = p_sw->lft_size;
+			p_sw->lft = malloc(p_sw->lft_size);
 			if (!p_sw->lft)
 				return IB_INSUFFICIENT_MEMORY;
-			memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+			memset(p_sw->lft, OSM_NO_PATH, p_sw->lft_size);
 		}
 
 	}
diff --git a/opensm/opensm/osm_ucast_file.c b/opensm/opensm/osm_ucast_file.c
index 5b73ca5..136e0de 100644
--- a/opensm/opensm/osm_ucast_file.c
+++ b/opensm/opensm/osm_ucast_file.c
@@ -92,7 +92,18 @@ static void add_path(osm_opensm_t * p_osm,
 			new_lid);
 	}
 
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 	p_sw->new_lft[new_lid] = port_num;
+#else
+	if (!osm_switch_set_new_lft_entry(p_sw, new_lid, port_num,
+					  &p_osm->subn)) {
+		OSM_LOG(&p_osm->log, OSM_LOG_SYS,
+			"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 630F: "
+			"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+		exit(1);
+	}
+#endif
 	if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid &&
 	      osm_get_switch_by_guid(&p_osm->subn, port_guid)))
 		osm_switch_count_path(p_sw, port_num);
@@ -193,8 +204,7 @@ static int do_ucast_file_load(void *context)
 					cl_ntoh64(sw_guid));
 				continue;
 			}
-			memset(p_sw->new_lft, OSM_NO_PATH,
-			       IB_LID_UCAST_END_HO + 1);
+			memset(p_sw->new_lft, OSM_NO_PATH, p_sw->new_lft_size);
 		} else if (p_sw && !strncmp(p, "0x", 2)) {
 			p += 2;
 			lid = (uint16_t) strtoul(p, &q, 16);
diff --git a/opensm/opensm/osm_ucast_ftree.c b/opensm/opensm/osm_ucast_ftree.c
index 6ec6bc7..e37abb4 100644
--- a/opensm/opensm/osm_ucast_ftree.c
+++ b/opensm/opensm/osm_ucast_ftree.c
@@ -566,7 +566,7 @@ static ftree_sw_t *sw_create(IN ftree_fabric_t * p_ftree,
 		return NULL;
 
 	/* initialize lft buffer */
-	memset(p_osm_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+	memset(p_osm_sw->new_lft, OSM_NO_PATH, p_osm_sw->new_lft_size);
 	p_sw->hops = malloc((p_osm_sw->max_lid_ho + 1) * sizeof(*(p_sw->hops)));
 	if (p_sw->hops == NULL)
 		return NULL;
@@ -2236,8 +2236,22 @@ fabric_route_upgoing_by_going_down(IN ftree_fabric_t * p_ftree,
 
 		/* setting fwd tbl port only if this is real LID */
 		if (is_real_lid) {
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 			p_remote_sw->p_osm_sw->new_lft[target_lid] =
 			    p_min_port->remote_port_num;
+#else
+			if (!osm_switch_set_new_lft_entry(p_remote_sw->p_osm_sw,
+							  target_lid,
+							  p_min_port->remote_port_num,
+							  &p_ftree->p_osm->subn)) {
+
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+					"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB15: osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					exit(1);
+			}
+#endif
 			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
 				"Switch %s: set path to CA LID %u through port %u\n",
 				tuple_to_str(p_remote_sw->tuple),
@@ -2459,6 +2473,7 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 			/* We update the LFT only if this LID isn't already present. */
 
 			/* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 			if ((p_remote_sw->p_osm_sw->new_lft[target_lid] ==
 			     OSM_NO_PATH)
 			    ||
@@ -2470,6 +2485,28 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 
 				p_remote_sw->p_osm_sw->new_lft[target_lid] =
 				    p_min_port->remote_port_num;
+#else
+			if (target_lid >= p_remote_sw->p_osm_sw->new_lft_size ||
+			    ((p_remote_sw->p_osm_sw->new_lft[target_lid] ==
+			      OSM_NO_PATH) ||
+			     ((p_remote_sw->p_osm_sw->new_lft[target_lid] !=
+			       OSM_NO_PATH) &&
+			      (current_hops + 1 <
+			       sw_get_least_hops(p_remote_sw, target_lid))))) {
+
+				if (!osm_switch_set_new_lft_entry(p_remote_sw->p_osm_sw,
+								  target_lid,
+								  p_min_port->remote_port_num,
+								  &p_ftree->p_osm->subn)) {
+					OSM_LOG(&p_ftree->p_osm->log,
+						OSM_LOG_SYS,
+						"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					OSM_LOG(&p_ftree->p_osm->log,
+						OSM_LOG_ERROR, "ERR AB16: "
+						"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					exit(1);
+				}
+#endif
 				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
 					"Switch %s: set path to CA LID %u through port %u\n",
 					tuple_to_str(p_remote_sw->tuple),
@@ -2540,7 +2577,12 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 		p_remote_sw = p_group->remote_hca_or_sw.p_sw;
 
 		/* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 		if (p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH)
+#else
+		if (target_lid < p_remote_sw->p_osm_sw->new_lft_size &&
+		    p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH)
+#endif
 			if (current_hops + 1 >=
 			    sw_get_least_hops(p_remote_sw, target_lid))
 				continue;
@@ -2576,8 +2618,21 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 
 		p_port = p_min_port;
 		//cl_ptr_vector_at(&p_group->ports, 0, (void *)&p_port);
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 		p_remote_sw->p_osm_sw->new_lft[target_lid] =
 		    p_port->remote_port_num;
+#else
+		if (!osm_switch_set_new_lft_entry(p_remote_sw->p_osm_sw,
+						  target_lid,
+						  p_port->remote_port_num,
+						  &p_ftree->p_osm->subn)) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+				"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+				"ERR AB17: osm_switch_set_new_lft_entry realloc failed - exiting\n");
+			exit(1);
+		}
+#endif
 
 		/* On the remote switch that is pointed by the p_group,
 		   set hops for ALL the ports in the remote group. */
@@ -2609,7 +2664,12 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 		p_remote_sw = p_group->remote_hca_or_sw.p_sw;
 
 		/* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 		if (p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH)
+#else
+		if (target_lid < p_remote_sw->p_osm_sw->new_lft_size &&
+		    p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH)
+#endif
 			if (current_hops + 1 >=
 			    sw_get_least_hops(p_remote_sw, target_lid))
 				continue;
@@ -2645,9 +2705,21 @@ fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
 
 		p_port = p_min_port;
 		//cl_ptr_vector_at(&p_group->ports, 0, (void *)&p_port);
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 		p_remote_sw->p_osm_sw->new_lft[target_lid] =
 		    p_port->remote_port_num;
-
+#else
+		if (!osm_switch_set_new_lft_entry(p_remote_sw->p_osm_sw,
+						  target_lid,
+						  p_port->remote_port_num,
+						  &p_ftree->p_osm->subn)) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+				"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+				"ERR AB18: osm_switch_set_new_lft_entry realloc failed - exiting\n");
+			exit(1);
+		}
+#endif
 		/* On the remote switch that is pointed by the p_group,
 		   set hops for ALL the ports in the remote group. */
 
@@ -2771,7 +2843,20 @@ static void fabric_route_to_cns(IN ftree_fabric_t * p_ftree)
 			/* set local LFT(LID) to the port that is connected to HCA */
 			cl_ptr_vector_at(&p_leaf_port_group->ports, 0,
 					 (void *)&p_port);
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 			p_sw->p_osm_sw->new_lft[hca_lid] = p_port->port_num;
+#else
+			if (!osm_switch_set_new_lft_entry(p_sw->p_osm_sw,
+							  hca_lid,
+							  p_port->port_num,
+							  &p_ftree->p_osm->subn)) {
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+					"osm_switch_set_new_lft_entry realloc error - exiting\n");
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB19: osm_switch_set_new_lft_entry realloc error - exiting\n");
+				exit(1);
+			}
+#endif
 
 			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
 				"Switch %s: set path to CN LID %u through port %u\n",
@@ -2883,7 +2968,20 @@ static void fabric_route_to_non_cns(IN ftree_fabric_t * p_ftree)
 			cl_ptr_vector_at(&p_hca_port_group->ports, 0,
 					 (void *)&p_hca_port);
 			port_num_on_switch = p_hca_port->remote_port_num;
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 			p_sw->p_osm_sw->new_lft[hca_lid] = port_num_on_switch;
+#else
+			if (!osm_switch_set_new_lft_entry(p_sw->p_osm_sw,
+							  hca_lid,
+							  port_num_on_switch,
+							  &p_ftree->p_osm->subn)) {
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+					"osm_switch_set_new_lft_entry realloc error - exiting\n");
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB1A: osm_switch_set_new_lft_entry realloc error - exiting\n");
+					exit(1);
+			}
+#endif
 
 			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
 				"Switch %s: set path to non-CN HCA LID %u through port %u\n",
@@ -2941,7 +3039,19 @@ static void fabric_route_to_switches(IN ftree_fabric_t * p_ftree)
 		p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item);
 
 		/* set local LFT(LID) to 0 (route to itself) */
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 		p_sw->p_osm_sw->new_lft[p_sw->base_lid] = 0;
+#else
+		if (!osm_switch_set_new_lft_entry(p_sw->p_osm_sw,
+						  p_sw->base_lid, 0,
+						  &p_ftree->p_osm->subn)) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_SYS,
+				"osm_switch_set_new_lft_entry realloc error - exiting\n");
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+				"ERR AB1B: osm_switch_set_new_lft_entry realloc error - exiting\n");
+			exit(1);
+		}
+#endif
 
 		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
 			"Switch %s (LID %u): routing switch-to-switch paths\n",
diff --git a/opensm/opensm/osm_ucast_lash.c b/opensm/opensm/osm_ucast_lash.c
index 0a567b3..18088a9 100644
--- a/opensm/opensm/osm_ucast_lash.c
+++ b/opensm/opensm/osm_ucast_lash.c
@@ -1009,7 +1009,7 @@ static void populate_fwd_tbls(lash_t * p_lash)
 		current_guid = p_sw->p_node->node_info.port_guid;
 		sw = p_sw->priv;
 
-		memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+		memset(p_sw->new_lft, OSM_NO_PATH, p_sw->new_lft_size);
 
 		for (lid = 1; lid <= max_lid_ho; lid++) {
 			port = cl_ptr_vector_get(&p_subn->port_lid_tbl, lid);
@@ -1020,7 +1020,20 @@ static void populate_fwd_tbls(lash_t * p_lash)
 			if (p_dst_sw == p_sw) {
 				uint8_t egress_port = port->p_node->sw ? 0 :
 					port->p_physp->p_remote_physp->port_num;
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 				p_sw->new_lft[lid] = egress_port;
+#else
+				if (!osm_switch_set_new_lft_entry(p_sw, lid,
+								  egress_port,
+								  p_subn)) {
+					OSM_LOG(p_log, OSM_LOG_SYS,
+						"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D05: "
+						"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					exit(1);
+				}
+#endif
+
 				OSM_LOG(p_log, OSM_LOG_VERBOSE,
 					"LASH fwd MY SRC SRC GUID 0x%016" PRIx64
 					" src lash id (%d), src lid no (%u) src lash port (%d) "
@@ -1038,7 +1051,19 @@ static void populate_fwd_tbls(lash_t * p_lash)
 				uint8_t physical_egress_port =
 					get_next_port(sw, lash_egress_port);
 
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 				p_sw->new_lft[lid] = physical_egress_port;
+#else
+				if (!osm_switch_set_new_lft_entry(p_sw, lid,
+								  physical_egress_port,
+								  p_subn)) {
+					OSM_LOG(p_log, OSM_LOG_SYS,
+						"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D06:"
+					       "osm_switch_set_new_lft_entry realloc failed - exiting\n");
+					exit(1);
+				}
+#endif
 				OSM_LOG(p_log, OSM_LOG_VERBOSE,
 					"LASH fwd SRC GUID 0x%016" PRIx64
 					" src lash id (%d), "
diff --git a/opensm/opensm/osm_ucast_mgr.c b/opensm/opensm/osm_ucast_mgr.c
index 629f628..0a34e8f 100644
--- a/opensm/opensm/osm_ucast_mgr.c
+++ b/opensm/opensm/osm_ucast_mgr.c
@@ -298,7 +298,17 @@ static void ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr,
 	   We have selected the port for this LID.
 	   Write it to the forwarding tables.
 	 */
+#ifndef ENABLE_OSM_FT_HEAP_OPTIMIZATION
 	p_sw->new_lft[lid_ho] = port;
+#else
+	if (!osm_switch_set_new_lft_entry(p_sw, lid_ho, port, p_mgr->p_subn)) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_SYS,
+			"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0F: "
+			"osm_switch_set_new_lft_entry realloc failed - exiting\n");
+		exit(1);
+	}
+#endif
 	if (!is_ignored_by_port_prof) {
 		struct osm_remote_node *rem_node_used;
 		osm_switch_count_path(p_sw, port);
@@ -443,7 +453,7 @@ static void ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item,
 		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
 
 	/* Initialize LIDs in buffer to invalid port number. */
-	memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+	memset(p_sw->new_lft, OSM_NO_PATH, p_sw->new_lft_size);
 
 	if (p_mgr->p_subn->opt.lmc)
 		alloc_ports_priv(p_mgr);
@@ -492,7 +502,8 @@ static boolean_t set_next_lft_block(IN osm_switch_t * p_sw, IN osm_sm_t * p_sm,
 	OSM_LOG_ENTER(p_sm->p_log);
 
 	for (;
-	     (sts = osm_switch_get_lft_block(p_sw, block_id_ho, p_block));
+	     (sts = osm_switch_get_lft_block(p_sw, p_sm->p_subn, block_id_ho,
+					     p_block));
 	     block_id_ho++) {
 		if (!p_sw->need_update && !p_sm->p_subn->need_update &&
 		    !memcmp(p_block,



More information about the general mailing list