[ofa-general] [PATCH][7] opensm: build global geometry

Robert Pearson rpearson at systemfabricworks.com
Tue Nov 11 09:28:40 PST 2008


Sasha,

Here is the seventh patch implementing the mesh analysis algorithm.

This patch implements
      - routine to induce axes on mesh starting from seed node
      - code to report results of local analysis (should have been in
patch6)

Regards,

Bob Pearson

Signed-off-by: Bob Pearson <rpearson at systemfabricworks.com>
----
diff --git a/opensm/opensm/osm_mesh.c b/opensm/opensm/osm_mesh.c
index 30d09c2..65afae6 100644
--- a/opensm/opensm/osm_mesh.c
+++ b/opensm/opensm/osm_mesh.c
@@ -599,6 +599,239 @@ static void get_local_geometry(lash_t *p_lash)
 }
 
 /*
+ * seed_axes
+ *
+ * assign axes to the links of the seed switch
+ * assumes switch is of type cartesian mesh
+ * axes are numbered 1 to n i.e. +x => 1 -x => 2 etc.
+ * this assumes that if all distances are 2 that
+ * an axis has only 2 nodes so +A and -A collapse to +A
+ */
+static void seed_axes(lash_t *p_lash, int sw)
+{
+	mesh_node_t *node = p_lash->switches[sw]->node;
+	int n = node->num_links;
+	int i, j, c;
+
+	for (c = 1; c <= 2*node->dimension; c++) {
+		/*
+		 * find the next unassigned axis
+		 */
+		for (i = 0; i < n; i++) {
+			if (!node->axes[i])
+				break;
+		}
+
+		node->axes[i] = c++;
+
+		/*
+		 * find the matching opposite direction
+		 */
+		for (j = 0; j < n; j++) {
+			if (node->axes[j] || j == i)
+				continue;
+
+			if (node->matrix[i][j] != 2)
+				break;
+		}
+
+		if (j != n) {
+			node->axes[j] = c;
+		}
+	}
+}
+
+/*
+ * opposite
+ *
+ * compute the opposite of axis for switch
+ */
+static inline int opposite(switch_t *s, int axis)
+{
+	int i, j;
+	int negaxis = 1 + (1 ^ (axis - 1));
+
+	for (i = 0; i < s->node->num_links; i++) {
+		if (s->node->axes[i] == axis) {
+			for (j = 0; j < s->node->num_links; j++) {
+				if (j == i)
+					continue;
+				if (s->node->matrix[i][j] != 2)
+					return negaxis;
+			}
+
+			return axis;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * make_geometry
+ *
+ * induce a geometry on the switches
+ */
+static void make_geometry(lash_t *p_lash, int sw)
+{
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	int num_switches = p_lash->num_switches;
+	int sw1, sw2;
+	switch_t *s, *s1, *s2, *seed;
+	int i, j, k, l, n, m;
+	int change;
+
+	/*
+	 * assign axes to seed switch
+	 */
+	seed_axes(p_lash, sw);
+	seed = p_lash->switches[sw];
+
+	/*
+	 * induce axes in other switches until
+	 * there is no more change
+	 */
+	do {
+		change = 0;
+
+		/* phase 1 opposites */
+		for (sw1 = 0; sw1 < num_switches; sw1++) {
+			s1 = p_lash->switches[sw1];
+			n = s1->node->num_links;
+
+			for (i = 0; i < n; i++) {
+				if (!s1->node->axes[i])
+					continue;
+
+				/*
+				 * can't tell across if more than one
+				 * likely looking link
+				 */
+				m = 0;
+				for (j = 0; j < n; j++) {
+					if (j == i)
+						continue;
+
+					if (s1->node->matrix[i][j] != 2)
+						m++;
+				}
+
+				if (m != 1) {
+					continue;
+				}
+
+				for (j = 0; j < n; j++) {
+					if (j == i)
+						continue;
+
+					if (s1->node->matrix[i][j] != 2) {
+						if (s1->node->axes[j]) {
+							if
(s1->node->axes[j] != opposite(seed, s1->node->axes[i])) {
+
OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 1 mismatch\n");
+							}
+						} else {
+							s1->node->axes[j] =
opposite(seed, s1->node->axes[i]);
+							change++;
+						}
+					}
+				}
+			}
+		}
+
+		/* phase 2 switch to switch */
+		for (sw1 = 0; sw1 < num_switches; sw1++) {
+			s1 = p_lash->switches[sw1];
+			n = s1->node->num_links;
+
+			for (i = 0; i < n; i++) {
+				int l2 = s1->node->links[i]->link_id;
+
+				if (!s1->node->axes[i])
+					continue;
+
+				if (l2 == -1) {
+					printf("ERROR no reverse link\n");
+					continue;
+				}
+
+				sw2 = s1->node->links[i]->switch_id;
+				s2 = p_lash->switches[sw2];
+
+				if (!s2->node->axes[l2]) {
+					/*
+					 * set axis to opposite of
s1->axes[i]
+					 */
+					s2->node->axes[l2] = opposite(seed,
s1->node->axes[i]);
+					change++;
+				} else {
+					if (s2->node->axes[l2] !=
opposite(seed, s1->node->axes[i])) {
+						OSM_LOG(p_log,
OSM_LOG_DEBUG, "phase 2 mismatch\n");
+					}
+				}
+			}
+		}
+
+		/* Phase 3 corners */
+		for (sw1 = 0; sw1 < num_switches; sw1++) {
+			s = p_lash->switches[sw1];
+			n = s->node->num_links;
+
+			for (i = 0; i < n; i++) {
+				if (!s->node->axes[i])
+					continue;
+
+				for (j = 0; j < n; j++) {
+					if (i == j || !s->node->axes[j] ||
s->node->matrix[i][j] != 2)
+						continue;
+
+					s1 =
p_lash->switches[s->node->links[i]->switch_id];
+					s2 =
p_lash->switches[s->node->links[j]->switch_id];
+
+					/*
+					 * find switch (other than s1) that
neighbors i and j
+					 * have in common
+					 */
+					for (k = 0; k < s1->node->num_links;
k++) {
+						if
(s1->node->links[k]->switch_id == sw1)
+							continue;
+
+						for (l = 0; l <
s2->node->num_links; l++) {
+							if
(s2->node->links[l]->switch_id == sw1)
+								continue;
+
+							if
(s1->node->links[k]->switch_id == s2->node->links[l]->switch_id) {
+								if
(s1->node->axes[k]) {
+									if
(s1->node->axes[k] != s->node->axes[j]) {
+
OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 3 mismatch\n");
+									}
+								} else {
+
s1->node->axes[k] = s->node->axes[j];
+
change++;
+								}
+
+								if
(s2->node->axes[l]) {
+									if
(s2->node->axes[l] != s->node->axes[i]) {
+
OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 3 mismatch\n");
+									}
+								} else {
+
s2->node->axes[l] = s->node->axes[i];
+
change++;
+								}
+								goto next_j;
+							}
+						}
+					}
+next_j:
+					;
+				}
+			}
+		}
+	} while(change);
+
+	return;
+}
+
+/*
  * osm_mesh_cleanup - free per mesh resources
  */
 void osm_mesh_cleanup(lash_t *p_lash)
@@ -652,8 +885,13 @@ static int mesh_create(lash_t *p_lash)
  */
 int osm_do_mesh_analysis(lash_t *p_lash)
 {
-	int ret = 0;
 	osm_log_t *p_log = &p_lash->p_osm->log;
+	int max_class = -1;
+	int max_class_num = 0;
+	int max_class_type = -1;
+	int i;
+	mesh_t *mesh;
+	switch_t *s;
 
 	OSM_LOG_ENTER(p_log);
 
@@ -671,11 +909,43 @@ int osm_do_mesh_analysis(lash_t *p_lash)
 	 */
 	get_local_geometry(p_lash);
 
-	printf("lash: do_mesh_analysis stub called\n");
+	/*
+	 * find dominant switch class
+	 */
+	for (i = 0; i < mesh->num_class; i++) {
+		if (mesh->class_count[i] > max_class_num) {
+			max_class = i;
+			max_class_num = mesh->class_count[i];
+			max_class_type = mesh->class_type[i];
+		}
+	}
+
+	s = p_lash->switches[max_class_type];
+
+	printf("lash: found %d node type%s\n", mesh->num_class,
(mesh->num_class == 1)? "" : "s");
+	printf("lash: %snode type is ", (mesh->num_class == 1)? "" : "most
common ");
+
+	if (s->node->type) {
+		struct _mesh_info *t = &mesh_info[s->node->type];
+
+		for (i = 0; i < t->dimension; i++) {
+			printf("%s%d%s", i? "X" : "", t->size[i],
+				(t->size[i] == 6)? "+" : "");
+		}
+		printf(" mesh\n");
+
+		p_lash->mesh->dimension = t->dimension;
+	} else {
+		printf("unknown geometry\n");
+	}
+
+	if (s->node->type) {
+		make_geometry(p_lash, max_class_type);
+	}
 
 	OSM_LOG_EXIT(p_log);
 
-	return ret;
+	return 0;
 }
 
 /*





More information about the general mailing list