[openib-general] [PATCH] Diags/ibportstate: For query op, add peer port checking of link width and speed active
Hal Rosenstock
halr at voltaire.com
Thu Oct 19 06:03:21 PDT 2006
Diags/ibportstate: For query op, add peer port checking of link width
and speed active
This is requiresthe combined route support in libibmad
Signed-off-by: Hal Rosenstock <halr at voltaire.com>
---
Index: src/ibportstate.c
===================================================================
--- src/ibportstate.c (revision 9870)
+++ src/ibportstate.c (working copy)
@@ -83,33 +83,29 @@ iberror(const char *fn, char *msg, ...)
/*******************************************/
-static char *
-get_node_info(ib_portid_t *dest, char *data, char **argv, int argc)
+static int
+get_node_info(ib_portid_t *dest, char *data)
{
int node_type;
if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))
- return "smp query nodeinfo failed";
+ return -1;
node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
if (node_type == IB_NODE_SWITCH) /* Switch NodeType ? */
return 0;
else
- return "Node type not switch";
+ return 1;
}
-static char *
-get_port_info(ib_portid_t *dest, char *data, char **argv, int argc, int port_op)
+static int
+get_port_info(ib_portid_t *dest, char *data, int portnum, int port_op)
{
char buf[2048];
- int portnum = 0;
char val[64];
- if (argc > 0)
- portnum = strtol(argv[0], 0, 0);
-
if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0))
- return "smp query portinfo failed";
+ return -1;
if (port_op != 4)
mad_dump_portstates(buf, sizeof buf, data, sizeof data);
@@ -123,18 +119,14 @@ get_port_info(ib_portid_t *dest, char *d
return 0;
}
-static char *
-set_port_info(ib_portid_t *dest, char *data, char **argv, int argc, int port_op)
+static int
+set_port_info(ib_portid_t *dest, char *data, int portnum, int port_op)
{
char buf[2048];
- int portnum = 0;
char val[64];
- if (argc > 0)
- portnum = strtol(argv[0], 0, 0);
-
if (!smp_set(data, dest, IB_ATTR_PORT_INFO, portnum, 0))
- return "smp set failed";
+ return -1;
if (port_op != 4)
mad_dump_portstates(buf, sizeof buf, data, sizeof data);
@@ -149,6 +141,55 @@ set_port_info(ib_portid_t *dest, char *d
return 0;
}
+static int
+get_link_width(int lwe, int lws)
+{
+ if (lwe == 255)
+ return lws;
+ else
+ return lwe;
+}
+
+static int
+get_link_speed(int lse, int lss)
+{
+ if (lse == 15)
+ return lss;
+ else
+ return lse;
+}
+
+static void
+validate_width(int width, int peerwidth, int lwa)
+{
+ if ((width & 0x8) && (peerwidth & 0x8)) {
+ if (lwa != 8)
+ printf("Peer ports operating at active width %d rather than 8 (12x)\n", lwa);
+ } else {
+ if ((width & 0x4) && (peerwidth & 0x4)) {
+ if (lwa != 4)
+ printf("Peer ports operating at active width %d rather than 4 (8x)\n", lwa);
+ } else {
+ if ((width & 0x2) && (peerwidth & 0x2))
+ if (lwa != 2)
+ printf("Peer ports operating at active width %d rather than 2 (4x)\n", lwa);
+ }
+ }
+}
+
+static void
+validate_speed(int speed, int peerspeed, int lsa)
+{
+ if ((speed & 0x4) && (peerspeed & 0x4)) {
+ if (lsa != 4)
+ printf("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)\n", lsa);
+ } else {
+ if ((speed & 0x2) && (peerspeed & 0x2))
+ if (lsa != 2)
+ printf("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)\n", lsa);
+ }
+}
+
void
usage(void)
{
@@ -179,13 +220,21 @@ main(int argc, char **argv)
ib_portid_t portid = {0};
ib_portid_t *sm_id = 0, sm_portid = {0};
extern int ibdebug;
+ int err;
int timeout = 0, udebug = 0;
char *ca = 0;
int ca_port = 0;
int port_op = 0; /* default to query */
int speed = 15;
- char *err;
+ int is_switch = 1;
+ int state, physstate, lwe, lws, lwa, lse, lss, lsa;
+ int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss, peerlsa;
+ int width, peerwidth, peerspeed;
char data[IB_SMP_DATA_SIZE];
+ ib_portid_t peerportid = {0};
+ int portnum = 0;
+ ib_portid_t selfportid = {0};
+ int selfport = 0;
static char const str_opts[] = "C:P:t:s:devDGVhu";
static const struct option long_opts[] = {
@@ -282,13 +331,26 @@ main(int argc, char **argv)
}
}
- if (port_op && (port_op != 4)) /* other than query or speed op */
- if ((err = get_node_info(&portid, data, argv+1, argc-1)))
- IBERROR("smpquery nodeinfo: %s", err);
-
- printf("Initial PortInfo:\n");
- if ((err = get_port_info(&portid, data, argv+1, argc-1, port_op)))
- IBERROR("smpquery portinfo: %s", err);
+ err = get_node_info(&portid, data);
+ if (err < 0)
+ IBERROR("smp query nodeinfo failed");
+ if (err) { /* not switch */
+ if (port_op == 0) /* query op */
+ is_switch = 0;
+ else if (port_op != 4) /* other than speed op */
+ IBERROR("smp query nodeinfo: Node type not switch");
+ }
+
+ if (argc-1 > 0)
+ portnum = strtol(argv[1], 0, 0);
+
+ if (port_op)
+ printf("Initial PortInfo:\n");
+ else
+ printf("PortInfo:\n");
+ err = get_port_info(&portid, data, portnum, port_op);
+ if (err < 0)
+ IBERROR("smp query portinfo failed");
/* Only if one of the "set" options is chosen */
if (port_op) {
@@ -303,13 +365,84 @@ main(int argc, char **argv)
mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
}
- if ((err = set_port_info(&portid, data, argv+1, argc-1, port_op)))
- IBERROR("smpset portinfo: %s", err);
+ err = set_port_info(&portid, data, portnum, port_op);
+ if (err < 0)
+ IBERROR("smp set portinfo failed");
if (port_op == 3) { /* Reset port - so also enable */
mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2); /* Polling */
- if ((err = set_port_info(&portid, data, argv+1, argc-1, port_op)))
- IBERROR("smpset portinfo: %s", err);
+ err = set_port_info(&portid, data, portnum, port_op);
+ if (err < 0)
+ IBERROR("smp set portinfo failed");
+ }
+ } else { /* query op */
+ /* only compare peer port if switch port */
+ if (is_switch) {
+ /* First, exclude SP0 */
+ if (portnum) {
+ /* Now, make sure PortState is Active */
+ /* Or is PortPhysicalState LinkUp sufficient ? */
+ mad_decode_field(data, IB_PORT_STATE_F, &state);
+ mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
+ if (state == 4) { /* Active */
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &lwe );
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &lws);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &lwa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &lss);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &lsa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &lse);
+
+ /* Setup portid for peer port */
+ memcpy(&peerportid, &portid, sizeof(peerportid));
+ peerportid.drpath.cnt = 1;
+ peerportid.drpath.p[1] = portnum;
+
+ /* Set DrSLID to local lid */
+ if (ib_resolve_self(&selfportid, &selfport, 0) < 0)
+ IBERROR("could not resolve self");
+ peerportid.drpath.drslid = selfportid.lid;
+ peerportid.drpath.drdlid = 0xffff;
+
+ /* Get peer port NodeInfo to obtain peer port number */
+ err = get_node_info(&peerportid, data);
+ if (err < 0)
+ IBERROR("smp query nodeinfo failed");
+
+ mad_decode_field(data, IB_NODE_LOCAL_PORT_F, &peerlocalportnum);
+
+ printf("Peer PortInfo:\n");
+ /* Get peer port characteristics */
+ err = get_port_info(&peerportid, data, peerlocalportnum, port_op);
+ if (err < 0)
+ IBERROR("smp query peer portinfofailed");
+
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &peerlwe );
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &peerlws);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &peerlwa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &peerlss);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &peerlsa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &peerlse);
+
+ /* Now validate peer port characteristics */
+ /* Examine Link Width */
+ width = get_link_width(lwe, lws);
+ if (width & 0xe) { /* more than 1x */
+ peerwidth = get_link_width(peerlwe, peerlws);
+ if (peerwidth & 0xe)
+ /* Look at active widths */
+ validate_width(width, peerwidth, lwa);
+ }
+
+ /* Examine Link Speed */
+ speed = get_link_speed(lse, lss);
+ if (speed & 0x6) { /* more than 2.5 Gbps */
+ peerspeed = get_link_speed(peerlse, peerlss);
+ if (peerspeed & 0x6)
+ /* Look at active speeds */
+ validate_speed(speed, peerspeed, lsa);
+ }
+ }
+ }
}
}
Index: man/ibportstate.8
===================================================================
--- man/ibportstate.8 (revision 9897)
+++ man/ibportstate.8 (working copy)
@@ -10,7 +10,9 @@ ibportstate \- handle port (physical) st
.SH DESCRIPTION
.PP
ibportstate allows the port state and port physical state of an IB port
-to be queried, or a switch port to be disabled, enabled, or reset. It
+to be queried (in addition to link width and speed being validated
+relative to the peer port when the port queried is a switch port),
+or a switch port to be disabled, enabled, or reset. It
also allows the link speed enabled on any IB port to be adjusted.
.SH OPTIONS
@@ -30,6 +32,13 @@ Port operations allowed
this setting)
(NOTE: Speed changes are not effected until the port goes through
link renegotiation)
+ query also validates port characteristics (link width and speed)
+ based on the peer port. This checking is done when the port
+ queried is a switch port as it relies on combined routing
+ (an initial LID route with directed routing to the peer) which
+ can only be done on a switch. This peer port validation feature
+ of query op requires LID routing to be functioning in the subnet.
+
.SH COMMON OPTIONS
More information about the general
mailing list