[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