Hey Sasha,

Here's a patch that does the previously discussed switchbalance console
option.  Algorithmically it does pretty much the exact same thing as the
check_lft_balance script, but everything is faster of course b/c opensm
already knows everything.

Al

-- 
Albert Chu
[EMAIL PROTECTED]
925-422-5311
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
>From d0369ffaf5575e49c50227f9808b111680fa90fc Mon Sep 17 00:00:00 2001
From: Albert L. Chu <[EMAIL PROTECTED]>
Date: Mon, 10 Mar 2008 10:59:15 -0700
Subject: [PATCH] add switchbalance command to console


Signed-off-by: Albert L. Chu <[EMAIL PROTECTED]>
---
 opensm/opensm/osm_console.c |  164 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 164 insertions(+), 0 deletions(-)

diff --git a/opensm/opensm/osm_console.c b/opensm/opensm/osm_console.c
index f9ee915..79b5795 100644
--- a/opensm/opensm/osm_console.c
+++ b/opensm/opensm/osm_console.c
@@ -53,6 +53,7 @@
 #include <opensm/osm_version.h>
 #include <complib/cl_passivelock.h>
 #include <opensm/osm_perfmgr.h>
+#include <opensm/osm_fwd_tbl.h>
 
 struct command {
 	char *name;
@@ -161,6 +162,17 @@ static void help_portstatus(FILE * out, int detail)
 
 }
 
+static void help_switchbalance(FILE * out, int detail)
+{
+	fprintf(out, "switchbalance [verbose] [guid]\n");
+	if (detail) {
+		fprintf(out, "output switch balancing information\n");
+		fprintf(out,
+			"  [verbose] -- verbose output\n"
+			"  [guid] -- limit results to specified guid\n");
+	}
+}
+
 #ifdef ENABLE_OSM_PERF_MGR
 static void help_perfmgr(FILE * out, int detail)
 {
@@ -693,6 +705,157 @@ static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
 	fprintf(out, "\n");
 }
 
+static void switchbalance_check(osm_opensm_t * p_osm, 
+				osm_switch_t *p_sw, 
+				FILE * out,
+				int verbose)
+{
+	uint8_t port_num;
+	uint8_t num_ports;
+	const cl_qmap_t *p_port_tbl;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_rem_physp;
+	osm_node_t *p_rem_node;
+	uint32_t count[255]; /* max ports is a uint8_t */
+	uint8_t output_ports[255];
+	uint8_t output_ports_count = 0;
+	uint32_t min_count = 0xFFFFFFFF;
+	uint32_t max_count = 0;
+	unsigned int i;
+
+	memset(count, '\0', sizeof(uint32_t)*255);
+
+	/* Count port usage */
+	p_port_tbl = &p_osm->subn.port_guid_tbl;
+	for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
+	     p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
+	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
+		uint16_t min_lid_ho;
+		uint16_t max_lid_ho;
+		uint16_t lid_ho;
+
+		/* Don't count switches in port usage */
+		if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
+			continue;
+
+		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+		if (min_lid_ho == 0 || max_lid_ho == 0)
+			continue;
+
+		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
+			port_num = osm_fwd_tbl_get(&(p_sw->fwd_tbl), lid_ho);
+			if (port_num == OSM_NO_PATH)
+				continue;
+
+			count[port_num]++;
+		}
+	}
+
+	num_ports = p_sw->num_ports;
+	for (port_num = 1; port_num < num_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+
+		/* if port is down/unhealthy, don't consider it in 
+		 * min/max calculations
+		 */
+		if (!p_physp
+		    || !osm_physp_is_healthy(p_physp)
+		    || !osm_physp_get_remote(p_physp))
+			continue;
+
+		p_rem_physp = osm_physp_get_remote(p_physp);
+		p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+		/* If we are directly connected to a CA, its not really 
+		 * up for balancing consideration.
+		 */
+		if (osm_node_get_type(p_rem_node) == IB_NODE_TYPE_CA)
+			continue;
+
+		output_ports[output_ports_count] = port_num;
+		output_ports_count++;
+
+		if (count[port_num] < min_count)
+			min_count = count[port_num];
+		if (count[port_num] > max_count)
+			max_count = count[port_num];
+	}
+
+	if (verbose || ((max_count - min_count) > 1)) {
+		if ((max_count - min_count) > 1)
+			fprintf(out, 
+				"Unbalanced Switch: 0x%016" PRIx64 " (%s)\n",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+		else
+			fprintf(out,
+				"Switch: 0x%016" PRIx64 " (%s)\n",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+
+		for (i = 0; i < output_ports_count; i++) {
+			fprintf(out,
+				"Port %d: %d\n",
+				output_ports[i],
+				count[output_ports[i]]);
+		}
+	}
+}
+
+static void switchbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	uint64_t guid = 0;
+	osm_switch_t *p_sw;
+	cl_qmap_t *p_sw_guid_tbl;
+	int verbose = 0;
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		char *p_end;
+
+		if (strcmp(p_cmd, "verbose") == 0) {
+			verbose++;
+			p_cmd = next_token(p_last);
+		}
+
+		if (p_cmd) {
+			guid = strtoul(p_cmd, &p_end, 0);
+			if (!guid || *p_end != '\0') {
+				fprintf(out, "Invalid guid specified\n");
+				help_switchbalance(out, 1);
+				return;
+			}
+		}
+	}
+
+	cl_plock_acquire(&p_osm->lock);
+	p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
+	if (guid) {
+		p_sw = (osm_switch_t *) cl_qmap_get(p_sw_guid_tbl, cl_hton64(guid));
+		if (p_sw == (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl)) {
+			fprintf(out, "guid not found\n");
+			goto lock_exit;
+		}
+
+		switchbalance_check(p_osm, p_sw, out, verbose);
+	}
+	else {
+		for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
+		     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
+		     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
+			switchbalance_check(p_osm,
+					    p_sw,
+					    out,
+					    verbose);
+	}
+lock_exit:
+	cl_plock_release(&p_osm->lock);
+	return;
+}
+
 #ifdef ENABLE_OSM_PERF_MGR
 static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
 {
@@ -784,6 +947,7 @@ static const struct command console_cmds[] = {
 	{"logflush", &help_logflush, &logflush_parse},
 	{"querylid", &help_querylid, &querylid_parse},
 	{"portstatus", &help_portstatus, &portstatus_parse},
+	{"switchbalance", &help_switchbalance, &switchbalance_parse},
 	{"version", &help_version, &version_parse},
 #ifdef ENABLE_OSM_PERF_MGR
 	{"perfmgr", &help_perfmgr, &perfmgr_parse},
-- 
1.5.1

_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to