Hey Sasha,
This follows up my switchbalance console option patch. This console
command is similar to the switchbalance one, but it determines if
individual ports have balanced routing on a switch, i.e. are they
forwarded to remote locations "evenly" and forwarded out of ports
"evenly".
Al
--
Albert Chu
[EMAIL PROTECTED]
925-422-5311
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
>From 413acff118dec7460b8e77cbeb25f8a23c40c0c3 Mon Sep 17 00:00:00 2001
From: Albert L. Chu <[EMAIL PROTECTED]>
Date: Wed, 12 Mar 2008 15:35:40 -0700
Subject: [PATCH] add portbalance command to console
Signed-off-by: Albert L. Chu <[EMAIL PROTECTED]>
---
opensm/opensm/osm_console.c | 202 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 202 insertions(+), 0 deletions(-)
diff --git a/opensm/opensm/osm_console.c b/opensm/opensm/osm_console.c
index 180e79f..c4a729f 100644
--- a/opensm/opensm/osm_console.c
+++ b/opensm/opensm/osm_console.c
@@ -173,6 +173,16 @@ static void help_switchbalance(FILE * out, int detail)
}
}
+static void help_portbalance(FILE * out, int detail)
+{
+ fprintf(out, "portbalance [switchguid]\n");
+ if (detail) {
+ fprintf(out, "output lid balancing information\n");
+ fprintf(out,
+ " [switchguid] -- limit results to specified switch guid\n");
+ }
+}
+
#ifdef ENABLE_OSM_PERF_MGR
static void help_perfmgr(FILE * out, int detail)
{
@@ -850,6 +860,197 @@ lock_exit:
return;
}
+static void portbalance_check(osm_opensm_t * p_osm,
+ osm_switch_t * p_sw, FILE * out)
+{
+ uint8_t port_num;
+ const cl_qmap_t *p_port_tbl;
+ osm_port_t *p_port;
+
+ 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)) {
+ uint32_t port_count[255]; /* max ports is a uint8_t */
+ osm_node_t *rem_node[255];
+ uint32_t rem_node_count;
+ uint32_t rem_count[255];
+ osm_physp_t *p_physp;
+ osm_physp_t *p_rem_physp;
+ osm_node_t *p_rem_node;
+ uint32_t port_min_count = 0xFFFFFFFF;
+ uint32_t port_max_count = 0;
+ uint32_t rem_min_count = 0xFFFFFFFF;
+ uint32_t rem_max_count = 0;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint8_t num_ports;
+ unsigned int i;
+
+ /* we only care about channel adapters */
+ if (osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_CA)
+ 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;
+
+ memset(port_count, '\0', sizeof(uint32_t) * 255);
+ memset(rem_node, '\0', sizeof(osm_node_t *) * 255);
+ rem_node_count = 0;
+ memset(rem_count, '\0', sizeof(uint32_t) * 255);
+
+ for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
+ boolean_t rem_node_found = FALSE;
+ unsigned int indx = 0;
+
+ port_num = osm_fwd_tbl_get(&(p_sw->fwd_tbl), lid_ho);
+ if (port_num == OSM_NO_PATH)
+ continue;
+
+ p_physp =
+ osm_node_get_physp_ptr(p_sw->p_node, port_num);
+
+ /* if port is down/unhealthy, can't calculate */
+ 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);
+
+ /* determine if we've seen this remote node before.
+ * If not, store it. If yes, update the counter
+ */
+ for (i = 0; i < rem_node_count; i++) {
+ if (rem_node[i] == p_rem_node) {
+ rem_node_found = TRUE;
+ indx = i;
+ break;
+ }
+ }
+
+ if (!rem_node_found) {
+ rem_node[rem_node_count] = p_rem_node;
+ rem_count[rem_node_count]++;
+ indx = rem_node_count;
+ rem_node_count++;
+ } else
+ rem_count[indx]++;
+
+ port_count[port_num]++;
+ }
+
+ if (!rem_node_count)
+ continue;
+
+ for (i = 0; i < rem_node_count; i++) {
+ if (rem_count[i] < rem_min_count)
+ rem_min_count = rem_count[i];
+ if (rem_count[i] > rem_max_count)
+ rem_max_count = rem_count[i];
+ }
+
+ num_ports = p_sw->num_ports;
+ for (i = 0; i < num_ports; i++) {
+ if (!port_count[i])
+ continue;
+ if (port_count[i] < port_min_count)
+ port_min_count = port_count[i];
+ if (port_count[i] > port_max_count)
+ port_max_count = port_count[i];
+ }
+
+ /* Output if this CA is being forwarded an unbalanced number of
+ * times to a destination.
+ */
+ if ((rem_max_count - rem_min_count) > 1) {
+ fprintf(out,
+ "Unbalanced CA Remote Forwarding: Switch 0x%016"
+ PRIx64 " (%s): ",
+ cl_ntoh64(p_sw->p_node->node_info.node_guid),
+ p_sw->p_node->print_desc);
+ fprintf(out, "CA 0x%016" PRIx64 " (%s): ",
+ cl_ntoh64(p_port->p_node->node_info.node_guid),
+ p_port->p_node->print_desc);
+ for (i = 0; i < rem_node_count; i++) {
+ fprintf(out,
+ "Dest 0x%016" PRIx64 "(%s) - %u ",
+ cl_ntoh64(rem_node[i]->node_info.
+ node_guid),
+ rem_node[i]->print_desc, rem_count[i]);
+ }
+ fprintf(out, "\n");
+ }
+
+ /* Output if this CA is being forwarded through a port an unbalanced
+ * number of times.
+ */
+ if ((port_max_count - port_min_count) > 1) {
+ fprintf(out,
+ "Unbalanced CA Port Forwarding: Switch 0x%016"
+ PRIx64 " (%s): ",
+ cl_ntoh64(p_sw->p_node->node_info.node_guid),
+ p_sw->p_node->print_desc);
+ fprintf(out, "CA 0x%016" PRIx64 " (%s): ",
+ cl_ntoh64(p_port->p_node->node_info.node_guid),
+ p_port->p_node->print_desc);
+ for (i = 0; i < num_ports; i++) {
+ if (!port_count[i])
+ continue;
+ fprintf(out, "Port %u - %u: ", i,
+ port_count[i]);
+ }
+ fprintf(out, "\n");
+ }
+ }
+}
+
+static void portbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+ char *p_cmd;
+ uint64_t switchguid = 0;
+ osm_switch_t *p_sw;
+ cl_qmap_t *p_sw_guid_tbl;
+
+ p_cmd = next_token(p_last);
+ if (p_cmd) {
+ char *p_end;
+
+ switchguid = strtoul(p_cmd, &p_end, 0);
+ if (!switchguid || *p_end != '\0') {
+ fprintf(out, "Invalid switchguid specified\n");
+ help_portbalance(out, 1);
+ return;
+ }
+ }
+
+ cl_plock_acquire(&p_osm->lock);
+ p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
+ if (switchguid) {
+ p_sw =
+ (osm_switch_t *) cl_qmap_get(p_sw_guid_tbl,
+ cl_hton64(switchguid));
+ if (p_sw == (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl)) {
+ fprintf(out, "switchguid not found\n");
+ goto lock_exit;
+ }
+
+ portbalance_check(p_osm, p_sw, out);
+ } 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))
+ portbalance_check(p_osm, p_sw, out);
+ }
+
+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)
{
@@ -942,6 +1143,7 @@ static const struct command console_cmds[] = {
{"querylid", &help_querylid, &querylid_parse},
{"portstatus", &help_portstatus, &portstatus_parse},
{"switchbalance", &help_switchbalance, &switchbalance_parse},
+ {"portbalance", &help_portbalance, &portbalance_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