[ofa-general] [PATCH] Add LMC support to DOR routing

Dale Purdy purdy at sgi.com
Sun Mar 15 07:42:07 PDT 2009


DOR routing equilizes traffic across redundant links representing
dimensions.  This change makes DOR compatible with LMC and tries to
equilize traffic across redundant links between LMC aliased LIDs.

Signed-off-by: Dale Purdy <purdy at sgi.com>
---
 opensm/include/opensm/osm_switch.h |    4 +++
 opensm/opensm/osm_switch.c         |   42 +++++++++++++++++++++++------------
 opensm/opensm/osm_ucast_mgr.c      |    8 +++++-
 3 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/opensm/include/opensm/osm_switch.h b/opensm/include/opensm/osm_switch.h
index 0b15e63..7ce28c5 100644
--- a/opensm/include/opensm/osm_switch.h
+++ b/opensm/include/opensm/osm_switch.h
@@ -167,6 +167,7 @@ struct osm_remote_guids_count {
 	struct osm_remote_node {
 		osm_node_t *node;
 		unsigned forwarded_to;
+		uint8_t port;
 	} guids[0];
 };
 /*
@@ -179,6 +180,9 @@ struct osm_remote_guids_count {
 *
 *	forwarded_to
 *		A count of lids forwarded to this node.
+*
+*	port
+*		Port number on the node.
 *********/
 
 /****f* OpenSM: Switch/osm_switch_delete
diff --git a/opensm/opensm/osm_switch.c b/opensm/opensm/osm_switch.c
index 6dde47c..d236329 100644
--- a/opensm/opensm/osm_switch.c
+++ b/opensm/opensm/osm_switch.c
@@ -303,6 +303,7 @@ osm_switch_recommend_path(IN const osm_switch_t * const p_sw,
 	osm_node_t *p_rem_node;
 	osm_node_t *p_rem_node_first = NULL;
 	struct osm_remote_node *p_remote_guid = NULL;
+	struct osm_remote_node null_remote_node = {NULL, 0, 0};
 
 	CL_ASSERT(lid_ho > 0);
 
@@ -413,12 +414,37 @@ osm_switch_recommend_path(IN const osm_switch_t * const p_sw,
 		check_count =
 		    osm_port_prof_path_count_get(&p_sw->p_prof[port_num]);
 
+		if (dor) {
+			/* Get the Remote Node */
+			p_rem_physp = osm_physp_get_remote(p_physp);
+			p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+			/* use the first dimension, but spread traffic
+			 * out among the group of ports representing
+			 * that dimension */
+			if (!p_rem_node_first)
+				p_rem_node_first = p_rem_node;
+			else if (p_rem_node != p_rem_node_first)
+				continue;
+			if (routing_for_lmc) {
+				struct osm_remote_guids_count *r = p_port->priv;
+				uint8_t rem_port = osm_physp_get_port_num(p_rem_physp);
+				int j;
+
+				for (j = 0; j < r->count; j++) {
+					p_remote_guid = &r->guids[j];
+					if ((p_remote_guid->node == p_rem_node)
+					    && (p_remote_guid->port == rem_port))
+						break;
+				}
+				if (j == r->count)
+					p_remote_guid = &null_remote_node;
+			}
 		/*
 		   Advanced LMC routing requires tracking of the
 		   best port by the node connected to the other side of
 		   it.
 		 */
-		if (routing_for_lmc) {
+		} else if (routing_for_lmc) {
 			/* Is the sys guid already used ? */
 			p_remote_guid = osm_switch_find_sys_guid_count(p_sw,
 								       p_port->priv,
@@ -454,20 +480,6 @@ osm_switch_recommend_path(IN const osm_switch_t * const p_sw,
 		   the count is min but also lower then the max subscribed
 		 */
 		if (check_count < least_paths) {
-			if (dor) {
-				/* Get the Remote Node */
-				p_rem_physp = osm_physp_get_remote(p_physp);
-				p_rem_node =
-				    osm_physp_get_node_ptr(p_rem_physp);
-				/* use the first dimension, but spread
-				 * traffic out among the group of ports
-				 * representing that dimension */
-				if (port_found) {
-					if (p_rem_node != p_rem_node_first)
-						continue;
-				} else
-					p_rem_node_first = p_rem_node;
-			}
 			port_found = TRUE;
 			best_port = port_num;
 			least_paths = check_count;
diff --git a/opensm/opensm/osm_ucast_mgr.c b/opensm/opensm/osm_ucast_mgr.c
index fe0a446..90d9732 100644
--- a/opensm/opensm/osm_ucast_mgr.c
+++ b/opensm/opensm/osm_ucast_mgr.c
@@ -186,19 +186,22 @@ __osm_ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * const p_mgr,
 /**********************************************************************
  **********************************************************************/
 static struct osm_remote_node *
-find_and_add_remote_sys(osm_switch_t *sw, uint8_t port,
+find_and_add_remote_sys(osm_switch_t *sw, uint8_t port, const boolean_t dor,
 			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;
+	uint8_t rem_port = osm_physp_get_port_num(p->p_remote_physp);
 
 	for (i = 0; i < r->count; i++)
 		if (r->guids[i].node == node)
+		  if (!dor || (r->guids[i].port == rem_port))
 			return &r->guids[i];
 
 	r->guids[i].node = node;
 	r->guids[i].forwarded_to = 0;
+	r->guids[i].port = rem_port;
 	r->count++;
 	return &r->guids[i];
 }
@@ -236,7 +239,7 @@ __osm_ucast_mgr_process_port(IN osm_ucast_mgr_t * const p_mgr,
 	if (lid_ho > max_lid_ho)
 		goto Exit;
 
-	if (lid_offset)
+	if (lid_offset && !p_mgr->is_dor)
 		/* ignore potential overflow - it is handled in osm_switch.c */
 		start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1) + 1;
 
@@ -302,6 +305,7 @@ __osm_ucast_mgr_process_port(IN osm_ucast_mgr_t * const p_mgr,
 		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_mgr->is_dor,
 							     p_port->priv)))
 			rem_node_used->forwarded_to++;
 	}
-- 
1.6.2




More information about the general mailing list