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 <[EMAIL PROTECTED]>
---

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
 




_______________________________________________
openib-general mailing list
openib-general@openib.org
http://openib.org/mailman/listinfo/openib-general

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

Reply via email to