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