Hi Jack,

On Thu, 2006-03-30 at 09:51, Jack Morgenstein wrote:
> management/diags: updating branch 1.0 from main trunk.

The ibnetdiscover/grouping changes are still meant only for the trunk
and are not yet ready for 1.0.

Also, saquery source has been checked in but there is a pending issue
and this was not yet included in the make so this is also for trunk
only.

I have been merging changes to 1.0 as appropriate.

-- Hal

> Index: include/grouping.h
> ===================================================================
> --- include/grouping.h        
> (.../branches/1.0/src/userspace/management/diags)       
> (revision 0)
> +++ include/grouping.h        (.../trunk/src/userspace/management/diags)      
> (revision 
> 6101)
> @@ -0,0 +1,93 @@
> +/*
> + * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * $Id$
> + */
> +
> +#ifndef _GROUPING_H_
> +#define _GROUPING_H_
> +
> +/*========================================================*/
> +/*               FABRIC SCANNER SPECIFIC DATA             */
> +/*========================================================*/
> +
> +#define SPINES_MAX_NUM 12
> +#define LINES_MAX_NUM 36
> +
> +typedef struct ChassisList ChassisList;
> +typedef struct AllChassisList AllChassisList;
> +
> +struct ChassisList {
> +     ChassisList *next;
> +     uint64_t chassisguid;
> +     int chassisnum;
> +     int chassistype;
> +     int nodecount;          /* used for grouping by SystemImageGUID */
> +     Node *spinenode[SPINES_MAX_NUM + 1];
> +     Node *linenode[LINES_MAX_NUM + 1];
> +};
> +
> +struct AllChassisList {
> +     ChassisList *first;
> +     ChassisList *current;
> +     ChassisList *last;
> +};
> +
> +/*========================================================*/
> +/*                CHASSIS RECOGNITION SPECIFIC DATA       */
> +/*========================================================*/
> +
> +/* Device IDs */
> +#define VTR_DEVID_IB_FC_ROUTER               0x5a00
> +#define VTR_DEVID_IB_IP_ROUTER               0x5a01
> +#define VTR_DEVID_ISR9600_SPINE              0x5a02
> +#define VTR_DEVID_ISR9600_LEAF               0x5a03
> +#define VTR_DEVID_HCA1                       0x5a04
> +#define VTR_DEVID_HCA2                       0x5a44
> +#define VTR_DEVID_HCA3                       0x6278
> +#define VTR_DEVID_SW_6IB4            0x5a05
> +#define VTR_DEVID_ISR9024            0x5a06
> +#define VTR_DEVID_ISR9288            0x5a07
> +#define VTR_DEVID_SLB24                      0x5a09
> +#define VTR_DEVID_SFB12                      0x5a08
> +#define VTR_DEVID_SFB4                       0x5a0b
> +#define VTR_DEVID_ISR9024_12         0x5a0c
> +#define VTR_DEVID_SLB8                       0x5a0d
> +#define VTR_DEVID_RLX_SWITCH_BLADE   0x5a20
> +#define VTR_DEVID_ISR9024_DDR                0x5a31
> +#define VTR_DEVID_SFB12_DDR          0x5a32
> +#define VTR_DEVID_SFB4_DDR           0x5a33
> +#define VTR_DEVID_SLB24_DDR          0x5a34
> +
> +enum ChassisType { UNRESOLVED_CT, ISR9288_CT, ISR9096_CT };
> +enum ChassisSlot { UNRESOLVED_CS, LINE_CS, SPINE_CS, SRBD_CS };
> +
> +#endif       /* _GROUPING_H_ */
> 
> Property changes on: include/grouping.h
> ___________________________________________________________________
> Name: svn:keywords
>    + Id
> 
> Index: include/ibnetdiscover.h
> ===================================================================
> --- include/ibnetdiscover.h   
> (.../branches/1.0/src/userspace/management/diags)       
> (revision 0)
> +++ include/ibnetdiscover.h   (.../trunk/src/userspace/management/diags)      
> (revision 6101)
> @@ -0,0 +1,95 @@
> +/*
> + * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * $Id$
> + */
> +
> +#ifndef _IBNETDISCOVER_H_
> +#define _IBNETDISCOVER_H_
> +
> +#define MAXHOPS      63
> +#define CA_NODE              1
> +#define SWITCH_NODE  2
> +
> +/* Vendor IDs */
> +#define VTR_VENDOR_ID                        0x8f1
> +#define TS_VENDOR_ID                 0x5ad
> +
> +
> +typedef struct Port Port;
> +typedef struct Node Node;
> +typedef struct ChassisRecord ChassisRecord;
> +
> +struct ChassisRecord {
> +     ChassisRecord *next;
> +
> +     unsigned char chassisnum;
> +     unsigned char anafanum;
> +     unsigned char slotnum;
> +     unsigned char chassistype;
> +     unsigned char chassisslot;
> +};
> +
> +struct Port {
> +     Port *next;
> +     uint64_t portguid;
> +     int portnum;
> +     int lid;
> +     int lmc;
> +     int state;
> +     int physstate;
> +
> +     Node *node;
> +     Port *remoteport;               /* null if SMA */
> +};
> +
> +struct Node {
> +     Node *htnext;
> +     Node *dnext;
> +     Port *ports;
> +     ib_portid_t path;
> +     int type;
> +     int dist;
> +     int numports;
> +     int localport;
> +     int smalid;
> +     uint32_t devid;
> +     uint32_t vendid;
> +     uint64_t sysimgguid;
> +     uint64_t nodeguid;
> +     uint64_t portguid;
> +     char nodedesc[64];
> +     uint8_t nodeinfo[64];
> +
> +     ChassisRecord *chrecord;
> +};
> +
> +#endif       /* _IBNETDISCOVER_H_ */
> 
> Property changes on: include/ibnetdiscover.h
> ___________________________________________________________________
> Name: svn:keywords
>    + Id
> 
> Index: src/ibnetdiscover.c
> ===================================================================
> --- src/ibnetdiscover.c       
> (.../branches/1.0/src/userspace/management/diags)       
> (revision 6101)
> +++ src/ibnetdiscover.c       (.../trunk/src/userspace/management/diags)      
> (revision 
> 6101)
> @@ -49,21 +49,33 @@
>  #include <umad.h>
>  #include <mad.h>
>  
> -#define MAXHOPS      63
> -#define CA_NODE              1
> -#define SWITCH_NODE  2
> +#include "ibnetdiscover.h"
>  
>  static int timeout = 2000;           /* ms */
>  static int dumplevel = 0;
> +static int chassisnum = 0;
>  static int verbose;
>  static FILE *f;
>  
> +extern void group_nodes();
> +extern char *portmapstring(Port *port);
> +extern char *get_chassis_type(unsigned char chassistype);
> +extern char *get_chassis_slot(unsigned char chassisslot);
> +extern uint64_t get_chassis_guid(unsigned char chassisnum);
> +
> +
>  #undef DEBUG
> -#define      DEBUG   if (verbose>1) IBWARN
> +#define      DEBUG   if (verbose > 1) IBWARN
>  #define IBERROR(fmt, args...)        iberror(__FUNCTION__, fmt, ## args)
>  
>  static char *argv0 = "ibnetdiscover";
>  
> +Node *nodesdist[MAXHOPS+1];     /* last is Ca list */
> +Node *mynode;
> +Port *myport;
> +int maxhops_discovered = 0;
> +
> +
>  void
>  iberror(const char *fn, char *msg, ...)
>  {
> @@ -87,46 +99,6 @@ iberror(const char *fn, char *msg, ...)
>       exit(-1);
>  }
>  
> -typedef struct Port Port;
> -typedef struct Node Node;
> -
> -struct Port {
> -     Port *next;
> -     uint64_t portguid;
> -     int portnum;
> -     int lid;
> -     int lmc;
> -     int state;
> -     int physstate;
> -
> -     Node *node;
> -     Port *remoteport;               /* null if SMA */
> -};
> -
> -struct Node {
> -     Node *htnext;
> -     Node *dnext;
> -     Port *ports;
> -     ib_portid_t path;
> -     int type;
> -     int dist;
> -     int numports;
> -     int localport;
> -     int smalid;
> -     uint32_t devid;
> -     uint32_t vendid;
> -     uint64_t sysimgguid;
> -     uint64_t nodeguid;
> -     uint64_t portguid;
> -     char nodedesc[64];
> -     uint8_t nodeinfo[64];
> -};
> -
> -Node *nodesdist[MAXHOPS+1];  /* last is Ca list */
> -Node *mynode;
> -Port *myport;
> -int maxhops_discovered = 0;
> -
>  int
>  get_port(Port *port, int portnum, ib_portid_t *portid)
>  {
> @@ -497,14 +469,64 @@ out_ids(Node *node)
>  }
>  
>  void
> -out_switch(Node *node)
> +out_chassis(Node *node)
>  {
> +     uint64_t guid;
> +
> +     /* GUID is not in ChassisRecord!!! */
> +     /* First, find chassis for this node in ChassisList */
> +     if (!node->chrecord->chassisnum)
> +             return;
> +     fprintf(f, "\nChassis %d", node->chrecord->chassisnum);
> +     guid = get_chassis_guid(node->chrecord->chassisnum);
> +     if (guid) {
> +#if __WORDSIZE == 64
> +             fprintf(f, " (guid 0x%lx)", guid);
> +#else
> +             fprintf(f, " (guid 0x%Lx)", guid);
> +#endif
> +     }
> +     fprintf(f, "\n");
> +}
> +
> +void
> +out_switch(Node *node, int group)
> +{
> +     char *str;
> +
> +     if (group) {
> +             if (node->chrecord) {
> +                     /* Start of a new chassis ? */
> +                     if (node->chrecord->chassisnum != chassisnum) {
> +                             chassisnum++;
> +                             out_chassis(node);
> +                     }
> +             }
> +     }
> +
>       out_ids(node);
>  #if __WORDSIZE == 64
> -     fprintf(f, "%s=0x%lx\n", "switchguid", node->nodeguid);
> +     fprintf(f, "%s=0x%lx", "switchguid", node->nodeguid);
>  #else
> -     fprintf(f, "%s=0x%Lx\n", "switchguid", node->nodeguid);
> +     fprintf(f, "%s=0x%Lx", "switchguid", node->nodeguid);
>  #endif
> +     if (group) {
> +             if (node->chrecord) {
> +                     if (node->chrecord->chassisnum) {
> +                             fprintf(f, "\t\t# Chassis %d ", 
> node->chrecord->chassisnum);
> +                             /* Currently, only if Voltaire chassis */
> +                             if (node->vendid == VTR_VENDOR_ID) {
> +                                     str = 
> get_chassis_type(node->chrecord->chassistype);
> +                                     if (str)
> +                                             fprintf(f, "%s ", str);
> +                                     str = 
> get_chassis_slot(node->chrecord->chassisslot);
> +                                     if (str)
> +                                             fprintf(f, "%s ", str);
> +                                     fprintf(f, "%d Chip %d", 
> node->chrecord->slotnum, 
> node->chrecord->anafanum);
> +                             }
> +                     }
> +             }
> +     }
>  
>       fprintf(f, "\nSwitch\t%d %s\t\t# %s port 0 lid %d\n",
>               node->numports, node_name(node),
> @@ -525,25 +547,44 @@ out_ca(Node *node)
>               clean_nodedesc(node->nodedesc));
>  }
>  
> +static void out_ext_port(Port *port, int group)
> +{
> +     char *str;
> +
> +     if (group) {
> +             if (port->node->chrecord && port->node->vendid == 
> VTR_VENDOR_ID) {
> +                     /* Currently, only if Voltaire chassis */
> +                     str = portmapstring(port);
> +                     if (str)
> +                             fprintf(f, "%s", str);
> +             }
> +     }
> +}
> +
>  void
> -out_switch_port(Port *port)
> +out_switch_port(Port *port, int group)
>  {
>       DEBUG("port %p:%d remoteport %p", port, port->portnum, 
> port->remoteport);
> -     fprintf(f, "[%d]\t%s[%d]\t\t\n",
> -             port->portnum, node_name(port->remoteport->node),
> +     fprintf(f, "[%d]", port->portnum);
> +     out_ext_port(port, group);
> +     fprintf(f, "\t%s[%d]", node_name(port->remoteport->node),
>               port->remoteport->portnum);
> +     out_ext_port(port->remoteport, group);
> +     fprintf(f, "\t\t\n");
>  }
>  
>  void
> -out_ca_port(Port *port)
> +out_ca_port(Port *port, int group)
>  {
> -     fprintf(f, "[%d]\t%s[%d]\t\t# lid %d lmc %d\n",
> -             port->portnum, node_name(port->remoteport->node),
> -             port->remoteport->portnum, port->lid, port->lmc);
> +     fprintf(f, "[%d]\t%s[%d]", port->portnum,
> +             node_name(port->remoteport->node),
> +             port->remoteport->portnum);
> +     out_ext_port(port->remoteport, group);
> +     fprintf(f, "\t\t# lid %d lmc %d\n", port->lid, port->lmc);
>  }
>  
>  int
> -dump_topology(int listtype)
> +dump_topology(int listtype, int group)
>  {
>       Node *node;
>       Port *port;
> @@ -567,7 +608,7 @@ dump_topology(int listtype)
>  
>                       DEBUG("SWITCH: dist %d node %p", dist, node);
>                       if (!listtype)
> -                             out_switch(node);
> +                             out_switch(node, group);
>                       else {
>                               if (listtype & SWITCH_NODE)
>                                       list_node(node);
> @@ -576,7 +617,7 @@ dump_topology(int listtype)
>  
>                       for (port = node->ports; port; port = port->next, i++)
>                               if (port->remoteport)
> -                                     out_switch_port(port);
> +                                     out_switch_port(port, group);
>               }
>       }
>  
> @@ -594,7 +635,7 @@ dump_topology(int listtype)
>  
>               for (port = node->ports; port; port = port->next, i++)
>                       if (port->remoteport)
> -                             out_ca_port(port);
> +                             out_ca_port(port, group);
>       }
>  
>       return i;
> @@ -602,8 +643,8 @@ dump_topology(int listtype)
>  
>  void
>  usage(void)
> -{
> -     fprintf(stderr, "Usage: %s [-d(ebug)] -e(rr_show) -v(erbose) -s(how) 
> -l(ist) 
> -H(ca_list) -S(witch_list) -V(ersion) -C ca_name -P ca_port "
> +{ 
> +     fprintf(stderr, "Usage: %s [-d(ebug)] -e(rr_show) -v(erbose) -s(how) 
> -l(ist) 
> -g(rouping) -H(ca_list) -S(witch_list) -V(ersion) -C ca_name -P ca_port "
>                       "-t(imeout) timeout_ms] [<netfile>]\n",
>                       argv0);
>       exit(-1);
> @@ -618,8 +659,9 @@ main(int argc, char **argv)
>       int udebug = 0, list = 0;
>       char *ca = 0;
>       int ca_port = 0;
> +     int group = 0;
>  
> -     static char const str_opts[] = "C:P:t:devslHSVhu";
> +     static char const str_opts[] = "C:P:t:devslgHSVhu";
>       static const struct option long_opts[] = {
>               { "C", 1, 0, 'C'},
>               { "P", 1, 0, 'P'},
> @@ -628,6 +670,7 @@ main(int argc, char **argv)
>               { "verbose", 0, 0, 'v'},
>               { "show", 0, 0, 's'},
>               { "list", 0, 0, 'l'},
> +             { "grouping", 0, 0, 'g'},
>               { "Hca_list", 0, 0, 'H'},
>               { "Switch_list", 0, 0, 'S'},
>               { "timeout", 1, 0, 't'},
> @@ -674,6 +717,9 @@ main(int argc, char **argv)
>               case 'l':
>                       list = CA_NODE | SWITCH_NODE;
>                       break;
> +             case 'g':
> +                     group = 1;
> +                     break;
>               case 'S':
>                       list = SWITCH_NODE;
>                       break;
> @@ -700,7 +746,10 @@ main(int argc, char **argv)
>       if (discover(&my_portid) < 0)
>               IBERROR("discover failed");
>  
> -     dump_topology(list);
> +     if (group)
> +             group_nodes();
> +
> +     dump_topology(list, group);
>  
>       exit(0);
>  }
> Index: src/saquery.c
> ===================================================================
> --- src/saquery.c     (.../branches/1.0/src/userspace/management/diags)       
> (revision 
> 0)
> +++ src/saquery.c     (.../trunk/src/userspace/management/diags)      
> (revision 6101)
> @@ -0,0 +1,422 @@
> +/*
> + * Copyright (c) 2006 The Regents of the University of California.
> + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
> + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
> + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
> + *
> + * Produced at Lawrence Livermore National Laboratory.
> + * Written by Ira Weiny <[EMAIL PROTECTED]>.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * $Id$
> + */
> +
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <assert.h>
> +
> +#define _GNU_SOURCE
> +#include <getopt.h>
> +
> +#include <infiniband/opensm/osm_log.h>
> +#include <infiniband/vendor/osm_vendor_api.h>
> +#include <infiniband/vendor/osm_vendor_sa_api.h>
> +#include <infiniband/opensm/osm_mad_pool.h>
> +
> +static char *argv0 = "saquery";
> +
> +/**
> + * Declare some globals because I don't want this to be too complex.
> + */
> +#define MAX_PORTS (8)
> +osmv_query_res_t   result;
> +osm_log_t          log_osm;
> +osm_mad_pool_t     mad_pool;
> +osm_vendor_t      *vendor = NULL;
> +int                osm_debug = 0;
> +
> +enum {
> +     ALL,
> +     LID_ONLY,
> +     GUID_ONLY,
> +} node_print_desc = ALL;
> +
> +char              *requested_name = NULL;
> +ib_net16_t         query_type = IB_MAD_ATTR_NODE_RECORD;
> +
> +/**
> + * Call back for the node record request.
> + */
> +void
> +query_res_cb(osmv_query_res_t *res)
> +{
> +     result = *res;
> +}
> +
> +void
> +print_node_record(ib_node_record_t *node_record)
> +{
> +     ib_node_info_t *p_ni = NULL;
> +     p_ni = &(node_record->node_info);
> +        
> +     switch (node_print_desc) {
> +     case LID_ONLY:
> +             printf("%d\n", cl_ntoh16(node_record->lid));
> +             return;
> +     case GUID_ONLY:
> +             printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
> +             return;
> +     case ALL:
> +     default:
> +             break;
> +        }
> +
> +     printf("NodeRecord dump:\n"
> +            "\t\t\t\tRID\n"
> +            "\t\t\t\tLid.....................0x%X\n"
> +            "\t\t\t\tReserved................0x%X\n"
> +            "\t\t\t\tNodeInfoDump\n"
> +            "\t\t\t\tbase_version............0x%X\n"
> +            "\t\t\t\tclass_version...........0x%X\n"
> +            "\t\t\t\tnode_type...............%s\n"
> +            "\t\t\t\tnum_ports...............0x%X\n"
> +            "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
> +            "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
> +            "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
> +            "\t\t\t\tpartition_cap...........0x%X\n"
> +            "\t\t\t\tdevice_id...............0x%X\n"
> +            "\t\t\t\trevision................0x%X\n"
> +            "\t\t\t\tport_num................0x%X\n"
> +            "\t\t\t\tvendor_id...............0x%X\n"
> +            "\t\t\t\tNodeDescription\n"
> +            "\t\t\t\t%s\n"
> +            "",
> +            cl_ntoh16(node_record->lid),
> +            cl_ntoh16(node_record->resv),
> +            p_ni->base_version,
> +            p_ni->class_version,
> +            ib_get_node_type_str( p_ni->node_type ),
> +            p_ni->num_ports,
> +            cl_ntoh64( p_ni->sys_guid ),
> +            cl_ntoh64( p_ni->node_guid ),
> +            cl_ntoh64( p_ni->port_guid ),
> +            cl_ntoh16( p_ni->partition_cap ),
> +            cl_ntoh16( p_ni->device_id ),
> +            cl_ntoh32( p_ni->revision ),
> +            ib_node_info_get_local_port_num( p_ni ),
> +            cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),
> +            node_record->node_desc.description
> +            );
> +}
> +
> +void
> +print_path_record(ib_path_rec_t *p_pr)
> +{
> +     printf("PathRecord dump:\n"
> +            "\t\t\t\tresv0...................0x%016" PRIx64 "\n"
> +            "\t\t\t\tdgid....................0x%016" PRIx64 " : "
> +            "0x%016" PRIx64 "\n"
> +            "\t\t\t\tsgid....................0x%016" PRIx64 " : "
> +            "0x%016" PRIx64 "\n"
> +            "\t\t\t\tdlid....................0x%X\n"
> +            "\t\t\t\tslid....................0x%X\n"
> +            "\t\t\t\thop_flow_raw............0x%X\n"
> +            "\t\t\t\ttclass..................0x%X\n"
> +            "\t\t\t\tnum_path_revers.........0x%X\n"
> +            "\t\t\t\tpkey....................0x%X\n"
> +            "\t\t\t\tsl......................0x%X\n"
> +            "\t\t\t\tmtu.....................0x%X\n"
> +            "\t\t\t\trate....................0x%X\n"
> +            "\t\t\t\tpkt_life................0x%X\n"
> +            "\t\t\t\tpreference..............0x%X\n"
> +            "\t\t\t\tresv2...................0x%X\n"
> +            "\t\t\t\tresv3...................0x%X\n"
> +            "",
> +            *(uint64_t*)p_pr->resv0,
> +            cl_ntoh64( p_pr->dgid.unicast.prefix ),
> +            cl_ntoh64( p_pr->dgid.unicast.interface_id ),
> +            cl_ntoh64( p_pr->sgid.unicast.prefix ),
> +            cl_ntoh64( p_pr->sgid.unicast.interface_id ),
> +            cl_ntoh16( p_pr->dlid ),
> +            cl_ntoh16( p_pr->slid ),
> +            cl_ntoh32( p_pr->hop_flow_raw ),
> +            p_pr->tclass,
> +            p_pr->num_path,
> +            cl_ntoh16( p_pr->pkey ),
> +            cl_ntoh16( p_pr->sl ),
> +            p_pr->mtu,
> +            p_pr->rate,
> +            p_pr->pkt_life,
> +            p_pr->preference,
> +            *(uint32_t*)&p_pr->resv2,
> +            *((uint16_t*)&p_pr->resv2 + 2)
> +            );
> +}
> +
> +static void
> +return_mad(void)
> +{
> +     /*
> +      * Return the IB query MAD to the pool as necessary.
> +      */
> +     if( result.p_result_madw != NULL ) {
> +             osm_mad_pool_put( &mad_pool, result.p_result_madw );
> +             result.p_result_madw = NULL;
> +     }
> +}
> +
> +/**
> + * Get the node records available.
> + */
> +static ib_api_status_t
> +get_all_records(osm_bind_handle_t bind_handle,
> +             ib_net16_t query_id,
> +             ib_net16_t attr_offset)
> +{
> +     ib_api_status_t   status;
> +     osmv_query_req_t  req;
> +     osmv_user_query_t user;
> +
> +     cl_memclr( &req, sizeof( req ) );
> +     cl_memclr( &user, sizeof( user ) );
> +
> +     user.attr_id = query_id;
> +     user.attr_offset = attr_offset;
> +
> +     req.query_type = OSMV_QUERY_USER_DEFINED;
> +     req.timeout_ms = 100;
> +     req.retry_cnt = 1;
> +     req.flags = OSM_SA_FLAGS_SYNC;
> +     req.query_context = NULL;
> +     req.pfn_query_cb = query_res_cb;
> +     req.p_query_input = &user;
> +     req.sm_key = 0;
> +
> +     if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {
> +             fprintf(stderr, "Query SA failed: %s\n",
> +                     ib_get_err_str(status));
> +             return (status);
> +     }
> +
> +     if (result.status != IB_SUCCESS) {
> +             fprintf(stderr, "Query result returned: %s\n",
> +                     ib_get_err_str(result.status));
> +             return (result.status);
> +     }
> +     return (status);
> +}
> +
> +static ib_api_status_t
> +print_node_records(osm_bind_handle_t bind_handle)
> +{
> +     int               i = 0;
> +     ib_node_record_t *node_record = NULL;
> +#if 0
> +     ib_net16_t        attr_offset = 
> ib_get_attr_offset(sizeof(*node_record));
> +#else
> +     ib_net16_t        attr_offset = 0;
> +#endif
> +     ib_api_status_t   status;
> +
> +     status  = get_all_records(bind_handle, IB_MAD_ATTR_NODE_RECORD, 
> attr_offset);
> +     if (status != IB_SUCCESS)
> +             return (status);
> +
> +     for (i = 0; i < result.result_cnt; i++) {
> +             node_record = osmv_get_query_node_rec(result.p_result_madw, i);
> +             if (!requested_name ||
> +                 (strcmp(requested_name,
> +                         node_record->node_desc.description) == 0))
> +                     print_node_record(node_record);
> +     }
> +     return_mad();
> +     return (status);
> +}
> +
> +static ib_api_status_t
> +print_path_records(osm_bind_handle_t bind_handle)
> +{
> +     int               i = 0;
> +     ib_path_rec_t    *path_record = NULL;
> +#if 0
> +     ib_net16_t        attr_offset = 
> ib_get_attr_offset(sizeof(*path_record));
> +#else
> +     ib_net16_t        attr_offset = 0;
> +#endif
> +     ib_api_status_t   status;
> +
> +     status = get_all_records(bind_handle, IB_MAD_ATTR_PATH_RECORD, 
> attr_offset);
> +     if (status != IB_SUCCESS)
> +             return (status);
> +
> +     for (i = 0; i < result.result_cnt; i++) {
> +             path_record = osmv_get_query_path_rec(result.p_result_madw, i);
> +             print_path_record(path_record);
> +     }
> +     return_mad();
> +     return (status);
> +}
> +
> +static osm_bind_handle_t
> +get_bind_handle(void)
> +{
> +     uint32_t           i = 0;
> +     uint64_t           port_guid = (uint64_t)-1;
> +     osm_bind_handle_t  bind_handle;
> +     ib_api_status_t    status;
> +     ib_port_attr_t     attr_array[MAX_PORTS];
> +     uint32_t           num_ports = MAX_PORTS;
> +
> +     osm_log_construct(&log_osm);
> +     if ((status = osm_log_init( &log_osm, TRUE,
> +                                 0x0001, NULL, TRUE )) != IB_SUCCESS) {
> +             fprintf(stderr, "Failed to init osm_log: %s\n",
> +                     ib_get_err_str(status));
> +             exit (-1);
> +     }
> +     osm_log_set_level(&log_osm, OSM_LOG_NONE);
> +     if (osm_debug)
> +             osm_log_set_level(&log_osm, OSM_LOG_DEFAULT_LEVEL);
> +
> +        vendor = osm_vendor_new(&log_osm, 100);
> +     osm_mad_pool_construct(&mad_pool);
> +     if ((status = osm_mad_pool_init(&mad_pool, &log_osm)) != IB_SUCCESS) {
> +             fprintf(stderr, "Failed to init mad pool: %s\n",
> +                     ib_get_err_str(status));
> +             exit (-1);
> +     }
> +
> +     if ((status = osm_vendor_get_all_port_attr(vendor, attr_array, 
> &num_ports)) != IB_SUCCESS) {
> +             fprintf(stderr, "Failed to get port attributes: %s\n",
> +                     ib_get_err_str(status));
> +             exit (-1);
> +     }
> +
> +     for (i = 0; i < num_ports; i++) {
> +             if (attr_array[i].link_state == IB_LINK_ACTIVE)
> +                     port_guid = attr_array[i].port_guid;
> +     }
> +
> +     if (port_guid == (uint64_t)-1) {
> +             fprintf(stderr, "Failed to find active port, check port status 
> with 
> \"ibstat\"\n");
> +             exit (-1);
> +     }
> +
> +     bind_handle = osmv_bind_sa(vendor, &mad_pool, port_guid);
> +
> +     if (bind_handle == OSM_BIND_INVALID_HANDLE) {
> +             fprintf(stderr, "Failed to bind to SA\n");
> +             exit(-1);
> +     }
> +     return (bind_handle);
> +}
> +
> +static void
> +clean_up(void)
> +{
> +     osm_mad_pool_destroy(&mad_pool);
> +     osm_vendor_delete(&vendor);
> +}
> +
> +void
> +usage(void)
> +{
> +     fprintf(stderr, "Usage: %s [-h -d -P -L -G][<name>]\n", argv0);
> +     fprintf(stderr, "   Queries node records by default\n");
> +     fprintf(stderr, "   -d enable debugging\n");
> +     fprintf(stderr, "   -P get PathRecord info\n");
> +     fprintf(stderr, "   -L Return just the Lid of the name specified\n");
> +     fprintf(stderr, "   -G Return just the Guid of the name specified\n");
> +     exit(-1);
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> +     int                ch = 0;
> +     osm_bind_handle_t  bind_handle;
> +
> +     static char const str_opts[] = "PLGdbh";
> +     static const struct option long_opts [] = {
> +        {"P", 0, 0, 'P'},
> +        {"L", 0, 0, 'L'},
> +        {"G", 0, 0, 'G'},
> +        {"d", 0, 0, 'd'},
> +        {"b", 0, 0, 'b'},
> +        {"help", 0, 0, 'h'},
> +        { }
> +     };
> +
> +     argv0 = argv[0];
> +
> +     while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL)) != -1) 
> {
> +             switch (ch) {
> +             case 'P':
> +                     query_type = IB_MAD_ATTR_PATH_RECORD;
> +                     break;
> +             case 'L':
> +                     node_print_desc = LID_ONLY;
> +                     break;
> +             case 'G':
> +                     node_print_desc = GUID_ONLY;
> +                     break;
> +             case 'd':
> +                     osm_debug = 1;
> +                     break;
> +             case 'h':
> +             default:
> +                     usage();
> +             }
> +     }
> +     argc -= optind;
> +     argv += optind;
> +
> +     if (argc)
> +             requested_name = argv[0];
> +
> +     bind_handle = get_bind_handle();
> +
> +     switch (query_type) {
> +     case IB_MAD_ATTR_NODE_RECORD:
> +             print_node_records(bind_handle);
> +             break;
> +     case IB_MAD_ATTR_PATH_RECORD:
> +             print_path_records(bind_handle);
> +             break;
> +     default:
> +             fprintf(stderr, "Unknown query type %d\n", query_type);
> +             break;
> +     }
> +
> +     clean_up();
> +     return (0);
> +}
> +
> 
> Property changes on: src/saquery.c
> ___________________________________________________________________
> Name: svn:keywords
>    + Id
> 
> Index: src/grouping.c
> ===================================================================
> --- src/grouping.c    (.../branches/1.0/src/userspace/management/diags)       
> (revision 
> 0)
> +++ src/grouping.c    (.../trunk/src/userspace/management/diags)      
> (revision 6101)
> @@ -0,0 +1,644 @@
> +/*
> + * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + * $Id$
> + */
> +
> +/*========================================================*/
> +/*               FABRIC SCANNER SPECIFIC DATA             */
> +/*========================================================*/
> +
> +#if HAVE_CONFIG_H
> +#  include <config.h>
> +#endif /* HAVE_CONFIG_H */
> +
> +#include <stdint.h>
> +
> +#include <common.h>
> +#include <mad.h>
> +
> +#include "ibnetdiscover.h"
> +#include "grouping.h"
> +
> +#define OUT_BUFFER_SIZE 16
> +
> +
> +extern Node *nodesdist[MAXHOPS+1];   /* last is CA list */
> +extern Node *mynode;
> +extern Port *myport;
> +extern int maxhops_discovered;
> +
> +AllChassisList mylist;
> +
> +char *ChassisTypeStr[3] = { "", "ISR9288", "ISR9096" };
> +char *ChassisSlotStr[4] = { "", "Line", "Spine", "SRBD" };
> +
> +
> +char *get_chassis_type(unsigned char chassistype)
> +{
> +     if (chassistype == UNRESOLVED_CT || chassistype > ISR9096_CT)
> +             return NULL;
> +     return ChassisTypeStr[chassistype];
> +}
> +
> +char *get_chassis_slot(unsigned char chassisslot)
> +{
> +     if (chassisslot == UNRESOLVED_CS || chassisslot > SRBD_CS)
> +             return NULL;
> +     return ChassisSlotStr[chassisslot];
> +}
> +
> +static struct ChassisList *find_chassisnum(unsigned char chassisnum) 
> +{
> +     ChassisList *current;
> +
> +     for (current = mylist.first; current; current = current->next) {
> +             if (current->chassisnum == chassisnum)
> +                     return current;
> +     }
> +
> +     return NULL;
> +}
> +
> +static uint64_t topspin_chassisguid(uint64_t guid)
> +{
> +     /* Byte 3 in system image GUID is chassis type, and */
> +     /* Byte 4 is location ID (slot) so just mask off byte 4 */
> +     return guid & 0xffffffff00ffffff;
> +}
> +
> +static uint64_t get_chassisguid(uint64_t guid, uint32_t vendid)
> +{
> +     if (vendid == TS_VENDOR_ID)
> +             return topspin_chassisguid(guid);
> +     else
> +             return guid;
> +}
> +
> +static struct ChassisList *find_chassisguid(uint64_t guid, uint32_t vendid)
> +{
> +     ChassisList *current;
> +     uint64_t chguid;
> +
> +     chguid = get_chassisguid(guid, vendid);
> +     for (current = mylist.first; current; current = current->next) {
> +             if (current->chassisguid == chguid)
> +                     return current;
> +     }
> +
> +     return NULL;
> +}
> +
> +uint64_t get_chassis_guid(unsigned char chassisnum)
> +{
> +     ChassisList *chassis;
> +
> +     chassis = find_chassisnum(chassisnum);
> +     if (chassis)
> +             return chassis->chassisguid;
> +     else
> +             return 0;
> +}
> +
> +static int is_router(Node *node)
> +{
> +     return (node->devid == VTR_DEVID_IB_FC_ROUTER ||
> +             node->devid == VTR_DEVID_IB_IP_ROUTER);
> +}
> +
> +static int is_spine_9096(Node *node)
> +{
> +     return (node->devid == VTR_DEVID_SFB4 ||
> +             node->devid == VTR_DEVID_SFB4_DDR);
> +}
> +
> +static int is_spine_9288(Node *node)
> +{
> +     return (node->devid == VTR_DEVID_SFB12 ||
> +             node->devid == VTR_DEVID_SFB12_DDR);
> +}
> +
> +static int is_spine(Node *node)
> +{
> +     return (is_spine_9096(node) || is_spine_9288(node));
> +}
> +
> +static int is_line_24(Node *node)
> +{
> +     return (node->devid == VTR_DEVID_SLB24 ||
> +             node->devid == VTR_DEVID_SLB24_DDR);
> +}
> +
> +static int is_line_8(Node *node)
> +{
> +     return (node->devid == VTR_DEVID_SLB8);
> +}
> +
> +static int is_line(Node *node)
> +{
> +     return (is_line_24(node) || is_line_8(node));
> +}
> +
> +static int is_chassis_switch(Node *node)
> +{
> +    return (is_spine(node) || is_line(node));
> +}
> +
> +/* this struct's helps find Line (Anafa) slot number while using spine 
> portnum */
> +int line_slot_2_sfb4[25]        = { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 
> 3, 
> 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
> +int anafa_line_slot_2_sfb4[25]  = { 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 
> 1, 
> 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2 };
> +int line_slot_2_sfb12[25]       = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 
> 7, 
> 7, 8, 8, 9, 9,10, 10, 11, 11, 12, 12 };
> +int anafa_line_slot_2_sfb12[25] = { 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 
> 1, 
> 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 };
> +
> +/* IPR FCR modules connectivity while using sFB4 port as reference */
> +int ipr_slot_2_sfb4_port[25]    = { 0, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 
> 3, 
> 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1 };
> +
> +/* this struct's helps find Spine (Anafa) slot number while using spine 
> portnum */
> +int spine12_slot_2_slb[25]      = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 
> 0, 
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> +int anafa_spine12_slot_2_slb[25]= { 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 
> 0, 
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> +int spine4_slot_2_slb[25]       = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 
> 0, 
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> +int anafa_spine4_slot_2_slb[25] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
> 0, 
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> +/*   reference                     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
> 12, 
> 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
> +
> +static void get_sfb_slot(Node *node, Port *lineport)
> +{
> +     ChassisRecord *ch = node->chrecord;
> +     
> +     ch->chassisslot = SPINE_CS;
> +     if (is_spine_9096(node)) {
> +             ch->chassistype = ISR9096_CT;
> +             ch->slotnum = spine4_slot_2_slb[lineport->portnum];
> +             ch->anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
> +     } else {
> +             ch->chassistype = ISR9288_CT;
> +             ch->slotnum = spine12_slot_2_slb[lineport->portnum];
> +             ch->anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
> +     }
> +}
> +
> +static void get_router_slot(Node *node, Port *spineport)
> +{
> +     ChassisRecord *ch = node->chrecord;
> +     int guessnum = 0;
> +
> +     if (!ch) { 
> +             if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))
> +                     IBPANIC("out of mem");
> +             ch = node->chrecord;
> +     }
> +
> +     ch->chassisslot = SRBD_CS;
> +     if (is_spine_9096(spineport->node)) {
> +             ch->chassistype = ISR9096_CT;
> +             ch->slotnum = line_slot_2_sfb4[spineport->portnum];
> +             ch->anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
> +     } else {
> +             ch->chassistype = ISR9288_CT;
> +             ch->slotnum = line_slot_2_sfb12[spineport->portnum];
> +             /* this is a smart guess based on nodeguids order on sFB-12 
> module */
> +             guessnum = spineport->node->nodeguid % 4;
> +             /* module 1 <--> remote anafa 3 */
> +             /* module 2 <--> remote anafa 2 */
> +             /* module 3 <--> remote anafa 1 */
> +             ch->anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2)); 
> +     }
> +}
> +
> +static void get_slb_slot(ChassisRecord *ch, Port *spineport)
> +{
> +     ch->chassisslot = LINE_CS;
> +     if (is_spine_9096(spineport->node)) {
> +             ch->chassistype = ISR9096_CT;
> +             ch->slotnum = line_slot_2_sfb4[spineport->portnum];
> +             ch->anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
> +     } else {
> +             ch->chassistype = ISR9288_CT;
> +             ch->slotnum = line_slot_2_sfb12[spineport->portnum];
> +             ch->anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
> +     }
> +}
> +
> +/*
> +     This function called for every Voltaire node in fabric
> +     It could be optimized so, but time overhead is very small
> +     and its only diag.util
> +*/
> +static void fill_chassis_record(Node *node)
> +{
> +     Port *port;
> +     Node *remnode = 0;
> +     ChassisRecord *ch = 0;
> +
> +     if (node->chrecord) /* somehow this node has already been passed */
> +             return;
> +     
> +     if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))
> +             IBPANIC("out of mem");
> +
> +     ch = node->chrecord;
> +
> +     /* node is router only in case of using unique lid */
> +     /* (which is lid of chassis router port) */
> +     /* in such case node->ports is actually a requested port... */
> +     if (is_router(node) && is_spine(node->ports->remoteport->node))
> +             get_router_slot(node, node->ports->remoteport);
> +     else if (is_spine(node)) {
> +             for (port = node->ports; port; port = port->next) {
> +                     if (!port->remoteport)
> +                             continue;
> +                     remnode = port->remoteport->node;
> +                     if (remnode->type != SWITCH_NODE) {
> +                             if (!remnode->chrecord)
> +                                     get_router_slot(remnode, port);
> +                             continue;
> +                     }
> +                     if (!ch->chassistype)
> +                             /* we assume here that remoteport belongs to 
> line */
> +                             get_sfb_slot(node, port->remoteport);
> +
> +                             /* we could break here, but need to find if 
> more routers connected */ 
> +             }
> +
> +     } else if (is_line(node)) {
> +             for (port = node->ports; port; port = port->next) {
> +                     if (port->portnum > 12)
> +                             continue;
> +                     if (!port->remoteport)
> +                             continue;
> +                     /* we assume here that remoteport belongs to spine */
> +                     get_slb_slot(ch, port->remoteport);
> +                     break;
> +             }
> +     }
> +
> +     return;
> +}
> +
> +static int get_line_index(Node *node)
> +{
> +     int retval = 3 * (node->chrecord->slotnum - 1) + 
> node->chrecord->anafanum;
> +
> +     if (retval > LINES_MAX_NUM || retval < 1) 
> +             IBPANIC("Grouping: Internal error");
> +     return retval;
> +}
> +
> +static int get_spine_index(Node *node)
> +{
> +     int retval;
> +
> +     if (is_spine_9288(node))
> +             retval = 3 * (node->chrecord->slotnum - 1) + 
> node->chrecord->anafanum;
> +     else
> +             retval = node->chrecord->slotnum; 
> +
> +     if (retval > SPINES_MAX_NUM || retval < 1) 
> +             IBPANIC("Grouping: Internal error");
> +     return retval;
> +}
> +
> +static void insert_line_router(Node *node, ChassisList *chassislist)
> +{
> +     int i = get_line_index(node);
> +
> +     if (chassislist->linenode[i]) 
> +             return;         /* already filled slot */
> +
> +     chassislist->linenode[i] = node;
> +     node->chrecord->chassisnum = chassislist->chassisnum;
> +}
> +
> +static void insert_spine(Node *node, ChassisList *chassislist)
> +{
> +     int i = get_spine_index(node);
> +
> +     if (chassislist->spinenode[i])
> +             return;         /* already filled slot */
> +
> +     chassislist->spinenode[i] = node;
> +     node->chrecord->chassisnum = chassislist->chassisnum;
> +}
> +
> +static void pass_on_lines_catch_spines(ChassisList *chassislist)
> +{
> +     Node *node, *remnode;
> +     Port *port;
> +     int i;
> +
> +     for (i = 1; i <= LINES_MAX_NUM; i++) {
> +             node = chassislist->linenode[i];
> +
> +             if (!(node && is_line(node))) 
> +                     continue;       /* empty slot or router */
> +
> +             for (port = node->ports; port; port = port->next) {
> +                     if (port->portnum > 12)
> +                             continue;
> +
> +                     if (!port->remoteport)
> +                             continue;
> +                     remnode = port->remoteport->node;
> +
> +                     if (!remnode->chrecord)
> +                             continue;       /* some error - spine not 
> initialized ? FIXME */
> +                     insert_spine(remnode, chassislist);
> +             }
> +     }
> +}
> +
> +static void pass_on_spines_catch_lines(ChassisList *chassislist)
> +{
> +     Node *node, *remnode;
> +     Port *port;
> +     int i;
> +
> +     for (i = 1; i <= SPINES_MAX_NUM; i++) {
> +             node = chassislist->spinenode[i];
> +             if (!node) 
> +                     continue;       /* empty slot */
> +             for (port = node->ports; port; port = port->next) {
> +                     if (!port->remoteport)
> +                             continue;
> +                     remnode = port->remoteport->node;
> +
> +                     if (!remnode->chrecord)
> +                             continue;       /* some error - line/router not 
> initialized ? FIXME */
> +                     insert_line_router(remnode, chassislist);
> +             }
> +     }
> +}
> +
> +/*
> +     Stupid interpolation algorithm...
> +     But nothing to do - have to be compliant with VoltaireSM/NMS 
> +*/
> +static void pass_on_spines_interpolate_chguid(ChassisList *chassislist)
> +{
> +     Node *node;
> +     int i;
> +     
> +     for (i = 1; i <= SPINES_MAX_NUM; i++) {
> +             node = chassislist->spinenode[i];
> +             if (!node) 
> +                     continue;       /* skip the empty slots */
> +
> +             /* take first guid less one: consistent with SM... */
> +             chassislist->chassisguid = node->nodeguid - 1;
> +             break;
> +     }
> +}    
> +
> +/*
> +     This function fills chassislist structure with all nodes
> +     in that chassis 
> +     chassislist structure = structure of one standalone chassis
> +*/
> +static void build_chassis(Node *node, ChassisList *chassislist)
> +{
> +     Node *remnode = 0;
> +     Port *port = 0;
> +    
> +     /* we get here with node = chassis_spine */
> +     chassislist->chassistype = node->chrecord->chassistype;
> +     insert_spine(node, chassislist);
> +
> +     /* loop: pass on all ports of node */
> +     for (port = node->ports; port; port = port->next) {
> +             if (!port->remoteport)
> +                     continue;
> +             remnode = port->remoteport->node;
> +
> +             if (!remnode->chrecord)
> +                     continue; /* some error - line or router not 
> initialized ? FIXME */
> +
> +             insert_line_router(remnode, chassislist);
> +     }
> +     
> +     pass_on_lines_catch_spines(chassislist);
> +     /* this pass needed for to catch routers, since routers connected only 
> */
> +     /* to spines in slot 1 or 4 and we could miss them first time */
> +     pass_on_spines_catch_lines(chassislist);
> +     
> +     /* additional 2 passes needed for to overcome a problem of pure 
> "in-chassis" 
> */
> +     /* connectivity - extra pass to ensure that all related chips/modules */
> +     /* inserted into the chassislist */
> +     pass_on_lines_catch_spines(chassislist);
> +     pass_on_spines_catch_lines(chassislist);
> +     pass_on_spines_interpolate_chguid(chassislist);
> +}
> +
> +/*========================================================*/
> +/*                INTERNAL TO EXTERNAL PORT MAPPING       */
> +/*========================================================*/
> +
> +/*
> +Description : On ISR9288/9096 external ports indexing
> +              is not matching the internal ( anafa ) port
> +              indexes. Use this MAP to translate the data you get from
> +              the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)
> + 
> + 
> +Module : sLB-24
> +                anafa 1             anafa 2
> +ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
> +int port | 22 23 24 18 17 16 | 22 23 24 18 17 16
> +ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
> +int port | 19 20 21 15 14 13 | 19 20 21 15 14 13
> +------------------------------------------------
> + 
> +Module : sLB-8
> +                anafa 1             anafa 2
> +ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
> +int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
> +ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
> +int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
> + 
> +----------->
> +                anafa 1             anafa 2
> +ext port | -  -  5  -  -  6  | -  -  7  -  -  8
> +int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
> +ext port | -  -  1  -  -  2  | -  -  3  -  -  4
> +int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
> +------------------------------------------------
> +
> +*/
> +
> +int int2ext_map_slb24[2][25] = {     
> +                                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
> 0, 6, 5, 4, 18, 17, 16, 1, 2, 3, 
> 13, 14, 15 },
> +                                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
> 0, 12, 11, 10, 24, 23, 22, 7, 8, 
> 9, 19, 20, 21 }
> +                             };
> +int int2ext_map_slb8[2][25] = {
> +                                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
> 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 
> 5, 5 },
> +                                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
> 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 
> 7, 7 }
> +                             };
> +/*   reference                       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
> 12, 13, 14, 15, 16, 
> 17, 18, 19, 20, 21, 22, 23, 24 }; */
> +
> +/*
> +     This function relevant only for line modules/chips
> +     Returns string with external port index  
> +*/
> +char *portmapstring(Port *port)
> +{
> +     static char mapping[OUT_BUFFER_SIZE];
> +     ChassisRecord *ch = port->node->chrecord;
> +     int portnum = port->portnum;
> +     int chipnum = 0;
> +     int pindex = 0;
> +     Node *node = port->node;
> +
> +     if (!ch || !is_line(node) || (portnum < 13 || portnum > 24))
> +             return NULL;
> +
> +     if (ch->anafanum < 1 || ch->anafanum > 2)
> +             return NULL;
> +
> +     memset(mapping, 0, sizeof(mapping));
> +     
> +     chipnum = ch->anafanum - 1;
> +
> +     if (is_line_24(node))
> +             pindex = int2ext_map_slb24[chipnum][portnum]; 
> +     else
> +             pindex = int2ext_map_slb8[chipnum][portnum];
> +
> +     sprintf(mapping, "[ext %d]", pindex);
> +
> +     return mapping;
> +}
> +
> +static void add_chassislist()
> +{
> +     if (!(mylist.current = calloc(1, sizeof(ChassisList))))
> +             IBPANIC("out of mem");
> +
> +     if (mylist.first == NULL) {
> +             mylist.first = mylist.current;
> +             mylist.last = mylist.current;
> +     } else {
> +             mylist.last->next = mylist.current;
> +             mylist.current->next = NULL;
> +             mylist.last = mylist.current;
> +     }
> +}
> +
> +/* 
> +     Main grouping function
> +     Algorithm:
> +     1. pass on every Voltaire node
> +     2. catch spine chip for every Voltaire node
> +             2.1 build/interpolate chassis around this chip
> +             2.2 go to 1.
> +     3. pass on non Voltaire nodes (SystemImageGUID based grouping)
> +     4. now group non Voltaire nodes by SystemImageGUID
> +*/
> +void group_nodes()
> +{
> +     Node *node;
> +     int dist;
> +     int chassisnum = 0;
> +     struct ChassisList *chassis;
> +
> +     mylist.first = NULL;
> +     mylist.current = NULL;
> +     mylist.last = NULL;
> +
> +     /* first pass on switches and build for every Voltaire node */ 
> +     /* an appropriate chassis record (slotnum and position) */
> +     /* according to internal connectivity */
> +     /* not very efficient but clear code so... */
> +     for (dist = 0; dist <= maxhops_discovered; dist++) {
> +             for (node = nodesdist[dist]; node; node = node->dnext) {
> +                     if (node->vendid == VTR_VENDOR_ID)
> +                             fill_chassis_record(node);
> +             }
> +     }
> +
> +     /* separate every Voltaire chassis from each other and build linked 
> list of 
> them */
> +     /* algorithm: catch spine and find all surrounding nodes */
> +     for (dist = 0; dist <= maxhops_discovered; dist++) {
> +             for (node = nodesdist[dist]; node; node = node->dnext) {
> +                     if (node->vendid != VTR_VENDOR_ID)
> +                             continue;
> +                     if (!node->chrecord || node->chrecord->chassisnum || 
> !is_spine(node))
> +                             continue;
> +
> +                     add_chassislist();
> +                     mylist.current->chassisnum = ++chassisnum;
> +                     build_chassis(node, mylist.current);
> +
> +             }
> +     }
> +
> +     /* now make pass on nodes for chassis which are not Voltaire */
> +     /* grouped by common SystemImageGUID */
> +     for (dist = 0; dist <= maxhops_discovered; dist++) {
> +             for (node = nodesdist[dist]; node; node = node->dnext) {
> +                     if (node->vendid == VTR_VENDOR_ID)
> +                             continue;
> +                     if (node->sysimgguid) {
> +                             chassis = find_chassisguid(node->sysimgguid,
> +                                                        node->vendid);
> +                             if (chassis)
> +                                     chassis->nodecount++;
> +                             else {
> +                                     /* Possible new chassis */
> +                                     add_chassislist();
> +                                     mylist.current->chassisguid = 
> get_chassisguid(node->sysimgguid, 
> node->vendid);
> +                                     mylist.current->nodecount = 1;
> +                             }
> +                     }
> +             }
> +     }
> +
> +     /* now, make another pass to see which nodes are part of chassis */
> +     /* (defined as chassis->nodecount > 1) */
> +     for (dist = 0; dist <= maxhops_discovered; dist++) {
> +             for (node = nodesdist[dist]; node; node = node->dnext) {
> +                     if (node->vendid == VTR_VENDOR_ID)
> +                             continue;
> +
> +                     if (node->sysimgguid) {
> +                             chassis = find_chassisguid(node->sysimgguid,
> +                                                        node->vendid);
> +                             if (chassis && chassis->nodecount > 1) {
> +                                     if (!chassis->chassisnum)
> +                                             chassis->chassisnum = 
> ++chassisnum;
> +                                     if (!node->chrecord) {
> +                                             if (!(node->chrecord = 
> calloc(1, sizeof(ChassisRecord))))
> +                                                     IBPANIC("out of mem");
> +                                             node->chrecord->chassisnum = 
> chassis->chassisnum;
> +                                     }
> +                             }
> +                     }
> +             }
> +     }
> +
> +}
> 
> Property changes on: src/grouping.c
> ___________________________________________________________________
> Name: svn:keywords
>    + Id
> 
> Index: Makefile.am
> ===================================================================
> --- Makefile.am       (.../branches/1.0/src/userspace/management/diags)       
> (revision 
> 6101)
> +++ Makefile.am       (.../trunk/src/userspace/management/diags)      
> (revision 6101)
> @@ -1,6 +1,7 @@
>  # $Id$
>  
> -INCLUDES = -I$(srcdir)/../libibcommon/include/infiniband \
> +INCLUDES = -I include \
> +        -I$(srcdir)/../libibcommon/include/infiniband \
>          -I$(srcdir)/../libibumad/include/infiniband \
>          -I$(srcdir)/../libibmad/include/infiniband \
>          -I$(includedir)/infiniband
> @@ -24,7 +25,7 @@ src_ibaddr_CFLAGS = -Wall
>  #                 $(libdir)/libibmad.la
>  # src_ibaddr_LDFLAGS = -Wl,--rpath -Wl,$(libdir)
>  
> -src_ibnetdiscover_SOURCES = src/ibnetdiscover.c
> +src_ibnetdiscover_SOURCES = src/ibnetdiscover.c src/grouping.c
>  src_ibnetdiscover_CFLAGS = -Wall
>  # src_ibnetdiscover_LDADD = $(libdir)/libibcommon.la \
>  #                      $(libdir)/libibumad.la \
> @@ -100,7 +101,7 @@ src_smpquery_CFLAGS = -Wall
>  #                 $(libdir)/libibmad.la
>  # src_smpquery_LDFLAGS = -Wl,--rpath -Wl,$(libdir)
>  
> -EXTRA_DIST = scripts diags.spec.in
> +EXTRA_DIST = scripts include diags.spec.in
>  
>  dist-hook: diags.spec
>          cp diags.spec $(distdir)
> 
> Property changes on: 
> ___________________________________________________________________
> Name: svn:ignore
>    + aclocal.m4
> autom4te.cache
> config.h
> config.h.in
> config.log
> config.status
> configure
> .deps
> libtool
> Makefile
> Makefile.in
> stamp-h1
> 
> 

_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

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

Reply via email to