[openib-general] Re: [PATCH 6 of 7] branch 1.0, management/diags: main trunk updates

Hal Rosenstock halr at voltaire.com
Thu Mar 30 06:59:01 PST 2006


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 <weiny2 at llnl.gov>.
> + *
> + * 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
> 
> 




More information about the general mailing list