[openib-general] [PATCH 2/4] Modular routing engine (unicast only yet).

Sasha Khapyorsky sashak at voltaire.com
Sat Jun 10 17:32:41 PDT 2006


This patch introduces routing_engine structure which may be used for
"plugging" new routing module. Currently only unicast callbacks are
supported (multicast can be added later). And existing routing module
is up-down 'updn', may be activated with '-R updn' option (instead of
old '-u'). General usage is:

 $ opensm -R 'module-name'

Signed-off-by: Sasha Khapyorsky <sashak at voltaire.com>
---

 osm/include/opensm/osm_opensm.h     |   17 ++++++++-
 osm/include/opensm/osm_subnet.h     |   16 ++------
 osm/include/opensm/osm_ucast_updn.h |   26 -------------
 osm/opensm/main.c                   |   26 +++++--------
 osm/opensm/osm_opensm.c             |   41 ++++++++++++++++++---
 osm/opensm/osm_subnet.c             |   23 ++++++------
 osm/opensm/osm_ucast_mgr.c          |   69 ++++++++++++++++++++++++-----------
 osm/opensm/osm_ucast_updn.c         |   69 ++++++++++++++++++-----------------
 8 files changed, 156 insertions(+), 131 deletions(-)

diff --git a/osm/include/opensm/osm_opensm.h b/osm/include/opensm/osm_opensm.h
index 3235ad4..3e6e120 100644
--- a/osm/include/opensm/osm_opensm.h
+++ b/osm/include/opensm/osm_opensm.h
@@ -92,6 +92,18 @@ BEGIN_C_DECLS
 *
 *********/
 
+/*
+ * routing engine structure - yet limited by ucast_fdb_assign and
+ *      ucast_build_fwd_tables (multicast callbacks may be added later)
+ */
+struct osm_routing_engine {
+	const char *name;
+	void *context;
+	int (*ucast_build_fwd_tables)(void *context);
+	int (*ucast_fdb_assign)(void *context);
+	void (*delete)(void *context);
+};
+
 /****s* OpenSM: OpenSM/osm_opensm_t
 * NAME
 *	osm_opensm_t
@@ -116,7 +128,7 @@ typedef struct _osm_opensm_t
   osm_log_t			log;
   cl_dispatcher_t	disp;
   cl_plock_t		lock;
-  updn_t         *p_updn_ucast_routing;
+  struct osm_routing_engine routing_engine;
   osm_stats_t		stats;
 } osm_opensm_t;
 /*
@@ -153,6 +165,9 @@ typedef struct _osm_opensm_t
 *	lock
 *		Shared lock guarding most OpenSM structures.
 *
+*	routing_engine
+*		Routing engine, will be initialized then used
+*
 *	stats
 *		Open SM statistics block
 *
diff --git a/osm/include/opensm/osm_subnet.h b/osm/include/opensm/osm_subnet.h
index 4db449d..a637367 100644
--- a/osm/include/opensm/osm_subnet.h
+++ b/osm/include/opensm/osm_subnet.h
@@ -272,13 +272,11 @@ typedef struct _osm_subn_opt
   uint32_t                 max_port_profile;
   osm_pfn_ui_extension_t   pfn_ui_pre_lid_assign;
   void *                   ui_pre_lid_assign_ctx;
-  osm_pfn_ui_extension_t   pfn_ui_ucast_fdb_assign;
-  void *                   ui_ucast_fdb_assign_ctx;
   osm_pfn_ui_mcast_extension_t pfn_ui_mcast_fdb_assign;
   void *                   ui_mcast_fdb_assign_ctx;
   boolean_t                sweep_on_trap;
   osm_testability_modes_t  testability_mode;
-  boolean_t                updn_activate;
+  char *                   routing_engine_name;
   char *                   updn_guid_file;
   boolean_t                exit_on_fatal;
   boolean_t                honor_guid2lid_file;
@@ -407,13 +405,6 @@ typedef struct _osm_subn_opt
 *  ui_pre_lid_assign_ctx
 *     A UI context (void *) to be provided to the pfn_ui_pre_lid_assign
 *
-*  pfn_ui_ucast_fdb_assign
-*     A UI function to be called instead of the ucast manager FDB
-*     configuration.
-*
-*  ui_ucast_fdb_assign_ctx
-*     A UI context (void *) to be provided to the pfn_ui_ucast_fdb_assign
-*
 *  pfn_ui_mcast_fdb_assign
 *     A UI function to be called inside the mcast manager instead of the
 *     call for the build spanning tree. This will be called on every
@@ -429,9 +420,8 @@ typedef struct _osm_subn_opt
 *  testability_mode
 *     Object that indicates if we are running in a special testability mode.
 *
-*  updn_activate
-*     Object that indicates if we are running the UPDN algorithm (TRUE) or 
-*     Min Hop Algorithm (FALSE)
+*  routing_engine_name
+*     Name of used routing engine (other than default Min Hop Algorithm)
 *
 *  updn_guid_file
 *     Pointer to name of the UPDN guid file given by User
diff --git a/osm/include/opensm/osm_ucast_updn.h b/osm/include/opensm/osm_ucast_updn.h
index 027056c..fbf8782 100644
--- a/osm/include/opensm/osm_ucast_updn.h
+++ b/osm/include/opensm/osm_ucast_updn.h
@@ -421,32 +421,6 @@ osm_subn_calc_up_down_min_hop_table(
 *	This function returns 0 when rankning has succeded , otherwise 1.
 ******/
 
-/****f* OpenSM: OpenSM/osm_updn_reg_calc_min_hop_table
-* NAME
-*	osm_updn_reg_calc_min_hop_table 
-*
-* DESCRIPTION
-*       Registration function to ucast routing manager (instead of 
-*       Min Hop Algorithm) 
-*
-* SYNOPSIS
-*/
-int
-osm_updn_reg_calc_min_hop_table(
-  IN updn_t * p_updn,
-  IN osm_subn_opt_t* p_opt );
-/*
-* PARAMETERS
-*
-* RETURN VALUES
-*	0 - on success , 1 - on failure
-*
-* NOTES
-*
-* SEE ALSO
-* osm_subn_calc_up_down_min_hop_table
-*********/
-
 /****** Osmsh: UpDown/osm_updn_find_root_nodes_by_min_hop
 * NAME
 *	osm_updn_find_root_nodes_by_min_hop
diff --git a/osm/opensm/main.c b/osm/opensm/main.c
index 22591eb..c888ed4 100644
--- a/osm/opensm/main.c
+++ b/osm/opensm/main.c
@@ -60,7 +60,6 @@ #include <opensm/osm_opensm.h>
 #include <complib/cl_types.h>
 #include <complib/cl_debug.h>
 #include <vendor/osm_vendor_api.h>
-#include <opensm/osm_ucast_updn.h>
 #include <opensm/osm_console.h>
 
 /********************************************************************
@@ -174,10 +173,10 @@ show_usage(void)
           "          may disrupt subnet traffic.\n"
           "          Without -r, OpenSM attempts to preserve existing\n"
           "          LID assignments resolving multiple use of same LID.\n\n");
-  printf( "-u\n"
-          "--updn\n"
-          "          This option activate UPDN algorithm instead of Min Hop\n"
-          "          algorithm (default).\n");
+  printf( "-R\n"
+          "--routing_engine <engine name>\n"
+          "          This option choose routing engine instead of Min Hop\n"
+          "          algorithm (default). Supported engines: updn\n");
   printf ("-a\n"
           "--add_guid_file <path to file>\n"
           "          Set the root nodes for the Up/Down routing algorithm\n"
@@ -524,7 +523,7 @@ #endif
   boolean_t             cache_options = FALSE;
   char                 *ignore_guids_file_name = NULL;
   uint32_t              val;
-  const char * const    short_option = "i:f:ed:g:l:s:t:a:P:NQuvVhorcyx";
+  const char * const    short_option = "i:f:ed:g:l:s:t:a:R:P:NQvVhorcyx";
 
   /*
     In the array below, the 2nd parameter specified the number
@@ -556,7 +555,7 @@ #endif
       {  "reassign_lids", 0, NULL, 'r'},
       {  "priority",      1, NULL, 'p'},
       {  "smkey",         1, NULL, 'k'},
-      {  "updn",          0, NULL, 'u'},
+      {  "routing_engine",1, NULL, 'R'},
       {  "add_guid_file", 1, NULL, 'a'},
       {  "cache-options", 0, NULL, 'c'},
       {  "stay_on_fatal", 0, NULL, 'y'},
@@ -776,9 +775,9 @@ #endif
       opt.sm_key = sm_key;
       break;
 
-    case 'u':
-      opt.updn_activate = TRUE;
-      printf(" Activate UPDN algorithm\n");
+    case 'R':
+      opt.routing_engine_name = optarg;
+      printf(" Activate \'%s\' routing engine\n", optarg);
       break;
 
     case 'a':
@@ -885,13 +884,6 @@ #endif
   setup_signals();
 
   osm_opensm_sweep( &osm );
-  /* since osm_opensm_init get opt as RO we'll set the opt value with UI pfn here */
-  /* Now do the registration */
-  if (opt.updn_activate)
-    if (osm_updn_reg_calc_min_hop_table(osm.p_updn_ucast_routing, &(osm.subn.opt))) {
-      status = IB_ERROR;
-      goto Exit;
-    }
 
   if( run_once_flag == TRUE )
   {
diff --git a/osm/opensm/osm_opensm.c b/osm/opensm/osm_opensm.c
index 8c422b5..52f06da 100644
--- a/osm/opensm/osm_opensm.c
+++ b/osm/opensm/osm_opensm.c
@@ -68,6 +68,37 @@ #include <opensm/osm_subnet.h>
 #include <opensm/osm_sm.h>
 #include <opensm/osm_vl15intf.h>
 
+struct routing_engine_module {
+	const char *name;
+	int (*setup)(osm_opensm_t *p_osm);
+};
+
+extern int osm_ucast_updn_setup(osm_opensm_t *p_osm);
+
+const static struct routing_engine_module routing_modules[] = {
+	{"null", NULL},
+	{"updn", osm_ucast_updn_setup },
+	{}
+};
+
+static int setup_routing_engine(osm_opensm_t *p_osm, const char *name)
+{
+	const struct routing_engine_module *r;
+	for (r = routing_modules ; r->name && *r->name ; r++) {
+		if(!strcmp(r->name, name)) {
+			p_osm->routing_engine.name = r->name;
+			if (r->setup(p_osm))
+				break;
+			osm_log (&p_osm->log, OSM_LOG_DEBUG,
+				 "opensm: setup_routing_engine: "
+				 "\'%s\' routing engine set up.\n",
+				 p_osm->routing_engine.name);
+			return 0;
+		}
+	}
+	return -1;
+}
+
 /**********************************************************************
  **********************************************************************/
 void
@@ -118,7 +149,8 @@ osm_opensm_destroy(
    cl_disp_shutdown( &p_osm->disp );
 
    /* do the destruction in reverse order as init */
-   updn_destroy( p_osm->p_updn_ucast_routing );
+   if (p_osm->routing_engine.delete)
+   	p_osm->routing_engine.delete(p_osm->routing_engine.context);
    osm_sa_destroy( &p_osm->sa );
    osm_sm_destroy( &p_osm->sm );
    osm_db_destroy( &p_osm->db );
@@ -252,11 +284,8 @@ #endif
    if( status != IB_SUCCESS )
       goto Exit;
 
-   /* HACK - the UpDown manager should have been a part of the osm_sm_t */
-   /* Init updn struct */
-   p_osm->p_updn_ucast_routing = updn_construct(  );
-   status = updn_init( p_osm->p_updn_ucast_routing );
-   if( status != IB_SUCCESS )
+   if( p_opt->routing_engine_name &&
+       setup_routing_engine(p_osm, p_opt->routing_engine_name))
       goto Exit;
 
  Exit:
diff --git a/osm/opensm/osm_subnet.c b/osm/opensm/osm_subnet.c
index 7c08556..27f97ab 100644
--- a/osm/opensm/osm_subnet.c
+++ b/osm/opensm/osm_subnet.c
@@ -484,13 +484,11 @@ osm_subn_set_default_opt(
   p_opt->max_port_profile = 0xffffffff;
   p_opt->pfn_ui_pre_lid_assign = NULL;
   p_opt->ui_pre_lid_assign_ctx = NULL;
-  p_opt->pfn_ui_ucast_fdb_assign = NULL;
-  p_opt->ui_ucast_fdb_assign_ctx = NULL;
   p_opt->pfn_ui_mcast_fdb_assign = NULL;
   p_opt->ui_mcast_fdb_assign_ctx = NULL;
   p_opt->sweep_on_trap = TRUE;
   p_opt->testability_mode = OSM_TEST_MODE_NONE;
-  p_opt->updn_activate = FALSE;
+  p_opt->routing_engine_name = NULL;
   p_opt->updn_guid_file = NULL;
   p_opt->exit_on_fatal = TRUE;
   subn_set_default_qos_options(&p_opt->qos_options);
@@ -911,9 +909,9 @@ osm_subn_parse_conf_file(
         "sweep_on_trap",
         p_key, p_val, &p_opts->sweep_on_trap);
 
-      __osm_subn_opts_unpack_boolean(
-        "updn_activate",
-        p_key, p_val, &p_opts->updn_activate);
+      __osm_subn_opts_unpack_charp(
+        "routing_engine",
+        p_key, p_val, &p_opts->routing_engine_name);
 
       __osm_subn_opts_unpack_charp(
         "log_file", p_key, p_val, &p_opts->log_file);
@@ -1089,12 +1087,13 @@ osm_subn_write_conf_file(
     opts_file,
     "#\n# ROUTING OPTIONS\n#\n"
     "# If true do not count switches as link subscriptions\n"
-    "port_profile_switch_nodes %s\n\n"
-    "# Activate the Up/Down routing algorithm\n"
-    "updn_activate %s\n\n",
-    p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE",
-    p_opts->updn_activate ? "TRUE" : "FALSE"
-    );
+    "port_profile_switch_nodes %s\n\n",
+    p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
+  if (p_opts->routing_engine_name)
+    fprintf( opts_file,
+             "# Routing engine\n"
+             "routing_engine %s\n\n",
+             p_opts->routing_engine_name);
   if (p_opts->updn_guid_file)
     fprintf( opts_file,
              "# The file holding the Up/Down root node guids\n"
diff --git a/osm/opensm/osm_ucast_mgr.c b/osm/opensm/osm_ucast_mgr.c
index cac7f9b..0c0d635 100644
--- a/osm/opensm/osm_ucast_mgr.c
+++ b/osm/opensm/osm_ucast_mgr.c
@@ -62,6 +62,7 @@ #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>
 
 #define LINE_LENGTH 256
 
@@ -269,7 +270,7 @@ osm_ucast_mgr_dump_ucast_routes(
       strcat( p_mgr->p_report_buf, "yes" );
     else
     {
-      if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign) {
+      if (p_mgr->p_subn->p_osm->routing_engine.ucast_fdb_assign) {
         ui_ucast_fdb_assign_func_defined = TRUE;
       } else {
         ui_ucast_fdb_assign_func_defined = FALSE;
@@ -708,7 +709,7 @@ __osm_ucast_mgr_process_port(
   node_guid = osm_node_get_node_guid(osm_switch_get_node_ptr( p_sw ) );
 
   /* Flag to mark whether or not a ui ucast fdb assign function was given */
-  if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
+  if (p_mgr->p_subn->p_osm->routing_engine.ucast_fdb_assign)
     ui_ucast_fdb_assign_func_defined = TRUE;
   else
     ui_ucast_fdb_assign_func_defined = FALSE;
@@ -753,7 +754,7 @@ __osm_ucast_mgr_process_port(
 
       /* Up/Down routing can cause unreachable routes between some 
          switches so we do not report that as an error in that case */
-      if (!p_mgr->p_subn->opt.updn_activate)
+      if (!p_mgr->p_subn->p_osm->routing_engine.ucast_fdb_assign)
       {
         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
                  "__osm_ucast_mgr_process_port: ERR 3A08: "
@@ -973,6 +974,18 @@ __osm_ucast_mgr_process_tbl(
 /**********************************************************************
  **********************************************************************/
 static void
+__osm_ucast_mgr_set_table_cb(
+  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_ucast_mgr_set_table( p_mgr, p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
 __osm_ucast_mgr_process_neighbors(
   IN cl_map_item_t* const  p_map_item,
   IN void* context )
@@ -1058,12 +1071,14 @@ osm_ucast_mgr_process(
 {
   uint32_t i;
   uint32_t iteration_max;
+  struct osm_routing_engine *p_routing_eng;
   osm_signal_t signal;
   cl_qmap_t *p_sw_guid_tbl;
 
   OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process );
 
   p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+  p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine;
 
   CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
 
@@ -1129,6 +1144,14 @@ osm_ucast_mgr_process(
              i
              );
 
+    if (p_routing_eng->ucast_build_fwd_tables &&
+        p_routing_eng->ucast_build_fwd_tables(p_routing_eng->context) == 0)
+    {
+      cl_qmap_apply_func( p_sw_guid_tbl,
+                          __osm_ucast_mgr_set_table_cb, p_mgr );
+    } /* fallback on the regular path in case of failures */
+    else
+    {
     /*
       This is the place where we can load pre-defined routes
       into the switches fwd_tbl structures.
@@ -1136,32 +1159,34 @@ osm_ucast_mgr_process(
       Later code will use these values if not configured for
       re-assignment.
     */
-    if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
-    {
-      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      if (p_routing_eng->ucast_fdb_assign)
       {
-        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
-                 "osm_ucast_mgr_process: "
-                 "Invoking UI function pfn_ui_ucast_fdb_assign\n");
-      }
-      p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign(p_mgr->p_subn->opt.ui_ucast_fdb_assign_ctx);
-    } else {
+        if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "osm_ucast_mgr_process: "
+                   "Invoking \'%s\' function ucast_fdb_assign\n",
+                   p_routing_eng->name);
+        }
+        p_routing_eng->ucast_fdb_assign(p_routing_eng->context);
+      } else {
         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
                  "osm_ucast_mgr_process: "
                  "UI pfn was not invoked\n");
-    }
+      }
 
-    osm_log(p_mgr->p_log, OSM_LOG_INFO,
-            "osm_ucast_mgr_process: "
-            "Min Hop Tables configured on all switches\n");
+      osm_log(p_mgr->p_log, OSM_LOG_INFO,
+              "osm_ucast_mgr_process: "
+              "Min Hop Tables configured on all switches\n");
 
-    /*
-      Now that the lid matrixes have been built, we can
-      build and download the switch forwarding tables.
-    */
+      /*
+        Now that the lid matrixes have been built, we can
+        build and download the switch forwarding tables.
+      */
 
-    cl_qmap_apply_func( p_sw_guid_tbl,
-                        __osm_ucast_mgr_process_tbl, p_mgr );
+      cl_qmap_apply_func( p_sw_guid_tbl,
+                          __osm_ucast_mgr_process_tbl, p_mgr );
+    }
 
     /* dump fdb into file: */
     if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
diff --git a/osm/opensm/osm_ucast_updn.c b/osm/opensm/osm_ucast_updn.c
index d80f7eb..8e36854 100644
--- a/osm/opensm/osm_ucast_updn.c
+++ b/osm/opensm/osm_ucast_updn.c
@@ -76,8 +76,9 @@ __updn_get_dir(IN uint8_t cur_rank,
                IN uint64_t cur_guid,
                IN uint64_t rem_guid)
 {
-  uint32_t i = 0, max_num_guids = osm.p_updn_ucast_routing->updn_ucast_reg_inputs.num_guids;
-  uint64_t *p_guid = osm.p_updn_ucast_routing->updn_ucast_reg_inputs.guid_list;
+  updn_t *p_updn = osm.routing_engine.context;
+  uint32_t i = 0, max_num_guids = p_updn->updn_ucast_reg_inputs.num_guids;
+  uint64_t *p_guid = p_updn->updn_ucast_reg_inputs.guid_list;
   boolean_t cur_is_root = FALSE , rem_is_root = FALSE;
 
   /* HACK: comes to solve root nodes connection, in a classic subnet root nodes does not connect
@@ -540,7 +541,7 @@ updn_init(
   p_updn->updn_ucast_reg_inputs.guid_list = NULL;
   p_updn->auto_detect_root_nodes = FALSE;
   /* Check if updn is activated , then fetch root nodes */
-  if (osm.subn.opt.updn_activate)
+  if (osm.routing_engine.context)
   {
     /*
        Check the source for root node list, if file parse it, otherwise
@@ -569,7 +570,7 @@ updn_init(
           {
             p_tmp = malloc(sizeof(uint64_t));
             *p_tmp = strtoull(line, NULL, 16);
-            cl_list_insert_tail(osm.p_updn_ucast_routing->p_root_nodes, p_tmp);
+            cl_list_insert_tail(p_updn->p_root_nodes, p_tmp);
           }
         }
         else
@@ -588,8 +589,8 @@ updn_init(
                "osm_opensm_init: "
                "UPDN - Root nodes fetching by file %s\n",
                osm.subn.opt.updn_guid_file);
-      guid_iterator = cl_list_head(osm.p_updn_ucast_routing->p_root_nodes);
-      while( guid_iterator != cl_list_end(osm.p_updn_ucast_routing->p_root_nodes) )
+      guid_iterator = cl_list_head(p_updn->p_root_nodes);
+      while( guid_iterator != cl_list_end(p_updn->p_root_nodes) )
       {
         osm_log( &osm.log, OSM_LOG_DEBUG,
                  "osm_opensm_init: "
@@ -600,7 +601,7 @@ updn_init(
     }
     else
     {
-      osm.p_updn_ucast_routing->auto_detect_root_nodes = TRUE;
+      p_updn->auto_detect_root_nodes = TRUE;
     }
     /* If auto mode detection reuired - will be executed in main b4 the assignment of UI Ucast */
   }
@@ -985,33 +986,6 @@ void __osm_updn_convert_list2array(IN up
 
 /**********************************************************************
  **********************************************************************/
-/* Registration function to ucast routing manager (instead of
-   Min Hop Algorithm) */
-int
-osm_updn_reg_calc_min_hop_table(
-  IN updn_t * p_updn,
-  IN osm_subn_opt_t* p_opt )
-{
-  OSM_LOG_ENTER(&(osm.log), osm_updn_reg_calc_min_hop_table);
-  /*
-     If root nodes were supplied by the user - we need to convert into array
-     otherwise, will be created & converted in callback function activation
-  */
-  if (!p_updn->auto_detect_root_nodes)
-  {
-    __osm_updn_convert_list2array(p_updn);
-  }
-  osm_log (&(osm.log), OSM_LOG_DEBUG,
-           "osm_updn_reg_calc_min_hop_table: "
-           "assigning ucast fdb UI function with updn callback\n");
-  p_opt->pfn_ui_ucast_fdb_assign = __osm_updn_call;
-  p_opt->ui_ucast_fdb_assign_ctx = (void *)p_updn;
-  OSM_LOG_EXIT(&(osm.log));
-  return 0;
-}
-
-/**********************************************************************
- **********************************************************************/
 /* Find Root nodes automatically by Min Hop Table info */
 int
 osm_updn_find_root_nodes_by_min_hop( OUT updn_t *  p_updn )
@@ -1210,3 +1184,30 @@ osm_updn_find_root_nodes_by_min_hop( OUT
   OSM_LOG_EXIT(&(osm.log));
   return 0;
 }
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __osm_updn_delete(void *context)
+{
+	updn_t *p_updn = context;
+	updn_destroy(p_updn);
+}
+
+int osm_ucast_updn_setup(osm_opensm_t *p_osm)
+{
+	updn_t *p_updn;
+	p_updn = updn_construct();
+	if (!p_updn)
+		return -1;
+	p_osm->routing_engine.context = p_updn;
+	p_osm->routing_engine.delete = __osm_updn_delete;
+	p_osm->routing_engine.ucast_fdb_assign = __osm_updn_call;
+
+	if (updn_init(p_updn) != IB_SUCCESS)
+		return -1;
+	if (!p_updn->auto_detect_root_nodes)
+		__osm_updn_convert_list2array(p_updn);
+
+	return 0;
+}




More information about the general mailing list