[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