[openib-general] [PATCH 3/4] New routing module which loads LFT tables from dump file.

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


This patch implements trivial routing module which able to load LFT
tables from dump file. Main features:
- support for unicast LFTs only, support for multicast can be added later
- this will run after min hop matrix calculation
- this will load switch LFTs according to the path entries introduced in
  the dump file
- no additional checks will be performed (like is port connected, etc)
- in case when fabric LIDs were changed this will try to reconstruct LFTs
  correctly if endport GUIDs are represented in the dump file (in order
  to disable this GUIDs may be removed from the dump file or zeroed)

The dump file format is compatible with output of 'ibroute' util and for
whole fabric may be generated with script like this:

  for sw_lid in `ibswitches | awk '{print $NF}'` ; do
	ibroute $sw_lid
  done > /path/to/dump_file

, or using DR paths:


  for sw_dr in `ibnetdiscover -v \
		| sed -ne '/^DR path .* switch /s/^DR path \[\(.*\)\].*$/\1/p' \
		| sed -e 's/\]\[/,/g' \
		| sort -u` ; do
	ibroute -D ${sw_dr}
  done > /path/to/dump_file


In order to activate new module use:

  opensm -R file -U /path/to/dump_file

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

 osm/include/opensm/osm_subnet.h |    5 +
 osm/opensm/Makefile.am          |    2 
 osm/opensm/main.c               |   16 ++
 osm/opensm/osm_opensm.c         |    2 
 osm/opensm/osm_subnet.c         |   10 ++
 osm/opensm/osm_ucast_file.c     |  258 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 289 insertions(+), 4 deletions(-)

diff --git a/osm/include/opensm/osm_subnet.h b/osm/include/opensm/osm_subnet.h
index a637367..ec1d056 100644
--- a/osm/include/opensm/osm_subnet.h
+++ b/osm/include/opensm/osm_subnet.h
@@ -277,6 +277,7 @@ typedef struct _osm_subn_opt
   boolean_t                sweep_on_trap;
   osm_testability_modes_t  testability_mode;
   char *                   routing_engine_name;
+  char *                   ucast_dump_file;
   char *                   updn_guid_file;
   boolean_t                exit_on_fatal;
   boolean_t                honor_guid2lid_file;
@@ -423,6 +424,10 @@ typedef struct _osm_subn_opt
 *  routing_engine_name
 *     Name of used routing engine (other than default Min Hop Algorithm)
 *
+*  ucast_dump_file
+*     Name of the unicast routing dump file from where switch
+*     forwearding tables will be loaded
+*
 *  updn_guid_file
 *     Pointer to name of the UPDN guid file given by User
 *
diff --git a/osm/opensm/Makefile.am b/osm/opensm/Makefile.am
index 7b1060a..5da88a4 100644
--- a/osm/opensm/Makefile.am
+++ b/osm/opensm/Makefile.am
@@ -83,7 +83,7 @@ opensm_SOURCES = main.c osm_console.c os
 		 osm_sw_info_rcv_ctrl.c osm_switch.c \
 		 osm_prtn.c osm_prtn_config.c osm_qos.c \
 		 osm_trap_rcv.c osm_trap_rcv_ctrl.c \
-		 osm_ucast_mgr.c osm_ucast_updn.c \
+		 osm_ucast_mgr.c osm_ucast_updn.c osm_ucast_file.c \
 		 osm_vl15intf.c osm_vl_arb_rcv.c \
 		 osm_vl_arb_rcv_ctrl.c st.c
 opensm_CFLAGS = -Wall $(OSMV_CFLAGS) -fno-strict-aliasing -DVENDOR_RMPP_SUPPORT $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
diff --git a/osm/opensm/main.c b/osm/opensm/main.c
index c888ed4..dfb2aec 100644
--- a/osm/opensm/main.c
+++ b/osm/opensm/main.c
@@ -175,8 +175,12 @@ show_usage(void)
           "          LID assignments resolving multiple use of same LID.\n\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");
+          "          This option chooses routing engine instead of Min Hop\n"
+          "          algorithm (default). Supported engines: updn, file\n");
+  printf( "-U\n"
+          "--ucast_file <file name>\n"
+          "          This option specifies name of the unicast dump file\n"
+          "          from where switch forwarding tables will be loaded.\nn");
   printf ("-a\n"
           "--add_guid_file <path to file>\n"
           "          Set the root nodes for the Up/Down routing algorithm\n"
@@ -523,7 +527,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:R:P:NQvVhorcyx";
+  const char * const    short_option = "i:f:ed:g:l:s:t:a:R:U:P:NQvVhorcyx";
 
   /*
     In the array below, the 2nd parameter specified the number
@@ -556,6 +560,7 @@ #endif
       {  "priority",      1, NULL, 'p'},
       {  "smkey",         1, NULL, 'k'},
       {  "routing_engine",1, NULL, 'R'},
+      {  "ucast_file"    ,1, NULL, 'U'},
       {  "add_guid_file", 1, NULL, 'a'},
       {  "cache-options", 0, NULL, 'c'},
       {  "stay_on_fatal", 0, NULL, 'y'},
@@ -780,6 +785,11 @@ #endif
       printf(" Activate \'%s\' routing engine\n", optarg);
       break;
 
+    case 'U':
+      opt.ucast_dump_file = optarg;
+      printf(" Ucast dump file is \'%s\'\n", optarg);
+      break;
+
     case 'a':
       /*
         Specifies port guids file
diff --git a/osm/opensm/osm_opensm.c b/osm/opensm/osm_opensm.c
index 52f06da..a189591 100644
--- a/osm/opensm/osm_opensm.c
+++ b/osm/opensm/osm_opensm.c
@@ -74,10 +74,12 @@ struct routing_engine_module {
 };
 
 extern int osm_ucast_updn_setup(osm_opensm_t *p_osm);
+extern int osm_ucast_file_setup(osm_opensm_t *p_osm);
 
 const static struct routing_engine_module routing_modules[] = {
 	{"null", NULL},
 	{"updn", osm_ucast_updn_setup },
+	{"file", osm_ucast_file_setup },
 	{}
 };
 
diff --git a/osm/opensm/osm_subnet.c b/osm/opensm/osm_subnet.c
index 27f97ab..0d46f85 100644
--- a/osm/opensm/osm_subnet.c
+++ b/osm/opensm/osm_subnet.c
@@ -489,6 +489,7 @@ osm_subn_set_default_opt(
   p_opt->sweep_on_trap = TRUE;
   p_opt->testability_mode = OSM_TEST_MODE_NONE;
   p_opt->routing_engine_name = NULL;
+  p_opt->ucast_dump_file = NULL;
   p_opt->updn_guid_file = NULL;
   p_opt->exit_on_fatal = TRUE;
   subn_set_default_qos_options(&p_opt->qos_options);
@@ -937,6 +938,10 @@ osm_subn_parse_conf_file(
         p_key, p_val, &p_opts->dump_files_dir);
 
       __osm_subn_opts_unpack_charp( 
+        "ucast_dump_file" ,
+        p_key, p_val, &p_opts->ucast_dump_file);
+
+      __osm_subn_opts_unpack_charp( 
         "updn_guid_file" ,
         p_key, p_val, &p_opts->updn_guid_file);
 
@@ -1094,6 +1099,11 @@ osm_subn_write_conf_file(
              "# Routing engine\n"
              "routing_engine %s\n\n",
              p_opts->routing_engine_name);
+  if (p_opts->ucast_dump_file)
+    fprintf( opts_file,
+             "# Ucast dump file name\n"
+             "ucast_dump_file %s\n\n",
+             p_opts->ucast_dump_file);
   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_file.c b/osm/opensm/osm_ucast_file.c
new file mode 100644
index 0000000..a68d9ec
--- /dev/null
+++ b/osm/opensm/osm_ucast_file.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM unicast routing module which loads
+ *    routes from the dump file
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+
+#define PARSEERR(log, file_name, lineno, fmt, arg...) \
+		osm_log(log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " fmt , \
+			file_name, lineno, ##arg )
+
+#define PARSEWARN(log, file_name, lineno, fmt, arg...) \
+		osm_log(log, OSM_LOG_VERBOSE, "PARSE WARN: %s:%u: " fmt , \
+			file_name, lineno, ##arg )
+
+static uint16_t remap_lid(osm_opensm_t *p_osm, uint16_t lid, ib_net64_t guid)
+{
+	osm_port_t *p_port;
+	uint16_t min_lid, max_lid;
+	uint8_t lmc;
+
+	p_port = (osm_port_t *)cl_qmap_get(&p_osm->subn.port_guid_tbl, guid);
+	if (!p_port ||
+	    p_port == (osm_port_t *)cl_qmap_end(&p_osm->subn.port_guid_tbl)) {
+		osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+			"remap_lid: cannot find port guid 0x%016" PRIx64
+			" , will use the same lid.\n", cl_ntoh64(guid));
+		return lid;
+	}
+
+	osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
+	if (min_lid <= lid && lid <= max_lid)
+		return lid;
+
+	lmc = osm_port_get_lmc(p_port);
+	return min_lid + (lid & ((1 << lmc) - 1));
+}
+
+static void add_path(osm_opensm_t * p_osm,
+		     osm_switch_t * p_sw, uint16_t lid, uint8_t port_num,
+		     ib_net64_t port_guid)
+{
+	uint16_t new_lid;
+	uint8_t old_port;
+
+	new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid;
+	old_port = osm_fwd_tbl_get(osm_switch_get_fwd_tbl_ptr(p_sw), new_lid);
+	if (old_port != OSM_NO_PATH && old_port != port_num) {
+		osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+			"add_path: LID collision is detected on switch "
+			"0x016%" PRIx64 ", will overwrite LID 0x%x entry.\n",
+			cl_ntoh64(osm_node_get_node_guid
+				  (osm_switch_get_node_ptr(p_sw))), new_lid);
+	}
+
+	osm_switch_set_path(p_sw, new_lid, port_num, TRUE);
+
+	osm_log(&p_osm->log, OSM_LOG_DEBUG,
+		"add_path: route 0x%04x(was 0x%04x) %u 0x%016" PRIx64
+		" is added to switch 0x%016" PRIx64 "\n",
+		new_lid, lid, port_num, cl_ntoh64(port_guid),
+		cl_ntoh64(osm_node_get_node_guid
+			  (osm_switch_get_node_ptr(p_sw))));
+}
+
+static void clean_sw_fwd_table(void *arg, void *context)
+{
+	osm_switch_t *p_sw = arg;
+	uint16_t lid, max_lid;
+
+	max_lid = osm_switch_get_max_lid_ho(p_sw);
+	for (lid = 1 ; lid <= max_lid ; lid++)
+		osm_switch_set_path(p_sw, lid, OSM_NO_PATH, TRUE);
+}
+
+static int do_ucast_file_load(void *context)
+{
+	char line[1024];
+	char *file_name;
+	FILE *file;
+	ib_net64_t sw_guid, port_guid;
+	osm_opensm_t *p_osm = context;
+	osm_switch_t *p_sw;
+	uint16_t lid;
+	uint8_t port_num;
+	unsigned lineno;
+
+	file_name = p_osm->subn.opt.ucast_dump_file;
+
+	if (!file_name) {
+		osm_log(&p_osm->log, OSM_LOG_ERROR,
+			"do_ucast_file_load: "
+			"ucast dump file name is not defined.\n");
+		return -1;
+	}
+
+	file = fopen(file_name, "r");
+	if (!file) {
+		osm_log(&p_osm->log, OSM_LOG_ERROR,
+			"do_ucast_file_load: "
+			"cannot open ucast dump file \'%s\'\n", file_name);
+		return -1;
+	}
+
+	cl_qmap_apply_func(&p_osm->subn.sw_guid_tbl, clean_sw_fwd_table, NULL);
+
+	lineno = 0;
+	p_sw = NULL;
+
+	while (fgets(line, sizeof(line) - 1, file) != NULL) {
+		char *p, *q;
+		lineno++;
+
+		p = line;
+		while (isspace(*p))
+			p++;
+
+		if (*p == '#')
+			continue;
+
+		if (!strncmp(p, "Multicast mlids", 15)) {
+			osm_log(&p_osm->log, OSM_LOG_ERROR,
+				"do_ucast_file_load: "
+				"Multicast dump file is detected. "
+				"Skip parsing.\n");
+		}
+		else if (!strncmp(p, "Unicast lids", 12)) {
+			q = strstr(p, " guid 0x");
+			if (!q) {
+				PARSEERR(&p_osm->log, file_name, lineno,
+					 "cannot parse switch definition\n");
+				return -1;
+			}
+			p = q + 6;
+			sw_guid = strtoll(p, &q, 16);
+			if (q && !isspace(*q)) {
+				PARSEERR(&p_osm->log, file_name, lineno,
+					 "cannot parse switch guid: \'%s\'\n",
+					 p);
+				return -1;
+			}
+			sw_guid = cl_hton64(sw_guid);
+
+			p_sw = (osm_switch_t *)cl_qmap_get(&p_osm->subn.sw_guid_tbl,
+							   sw_guid);
+			if (!p_sw ||
+			    p_sw == (osm_switch_t *)cl_qmap_end(&p_osm->subn.sw_guid_tbl)) {
+				p_sw = NULL;
+				osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+					"do_ucast_file_load: "
+					"cannot find switch %016" PRIx64 ".\n",
+					cl_ntoh64(sw_guid));
+				continue;
+			}
+		}
+		else if (p_sw && !strncmp(p, "0x", 2)) {
+			lid = strtoul(p, &q, 16);
+			if (q && !isspace(*q)) {
+				PARSEERR(&p_osm->log, file_name, lineno,
+					 "cannot parse lid: \'%s\'\n", p);
+				return -1;
+			}
+			p = q;
+			while (isspace(*p))
+				p++;
+			port_num = strtoul(p, &q, 10);
+			if (q && !isspace(*q)) {
+				PARSEERR(&p_osm->log, file_name, lineno,
+					 "cannot parse port: \'%s\'\n", p);
+				return -1;
+			}
+			p = q;
+			/* additionally try to exract guid */
+			q = strstr(p, " portguid 0x");
+			if (!q) {
+				PARSEWARN(&p_osm->log, file_name, lineno,
+					  "cannot find port guid "
+					  "(maybe broken dump): \'%s\'\n", p);
+				port_guid = 0;
+			}
+			else {
+				p = q + 10;
+				port_guid = strtoll(p, &q, 16);
+				if (!q && !isspace(*q) && *q != ':') {
+					PARSEWARN(&p_osm->log, file_name,
+						  lineno,
+						  "cannot parse port guid "
+						  "(maybe broken dump): "
+						  "\'%s\'\n", p);
+					port_guid = 0;
+				}
+			}
+			port_guid = cl_hton64(port_guid);
+			add_path(p_osm, p_sw, lid, port_num, port_guid);
+		}
+	}
+
+	fclose(file);
+	return 0;
+}
+
+int osm_ucast_file_setup(osm_opensm_t * p_osm)
+{
+	p_osm->routing_engine.context = (void *)p_osm;
+	p_osm->routing_engine.ucast_build_fwd_tables = do_ucast_file_load;
+	return 0;
+}




More information about the general mailing list