/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/ccs/lib/libperfstat/simplefcstat.c 1.2              */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2011,2012              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
static char sccsid[] = "@(#)91  1.2  src/bos/usr/ccs/lib/libperfstat/simplefcstat.c, libperfstat, bos720 2/10/12 04:18:29";

/* The sample program display the metrics *
 * related to each and every Individual   * 
 * Fiber Channel adapter in the LPAR          */

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

/* define default interval and count values */
#define INTERVAL_DEFAULT 1
#define COUNT_DEFAULT    1

/* Check value returned by malloc for NULL */

#define CHECK_FOR_MALLOC_NULL(X) {  if ((X) == NULL) {\
                                       perror ("malloc");\
                                       exit(2);\
                                     }\
                  }

int count = COUNT_DEFAULT, interval = INTERVAL_DEFAULT, tot=0;
int returncode=0;

/* store the data structures */

static perfstat_fcstat_t *statp=NULL ,*statq=NULL;

/* support for remote node statistics collection in a cluster environment */
perfstat_id_node_t nodeid;
static char nodename[MAXHOSTNAMELEN] = "";
static int collect_remote_node_stats = 0;

unsigned long long wwpn_id=0;
int fc_flag=0, wwpn_flag=0;
char fcadapter_name[MAXHOSTNAMELEN];
/*
 * NAME: showusage
 *       to display the usage
 *
 */

void showusage(char *cmd)
{
    fprintf (stderr, "usage: %s [-i <interval in seconds> ] [-c <number of iterations> ] [-n <node name in the cluster> ] [-a FC adapter name] [-w World Wide Port Name]] \n", cmd);
    exit(1);
}


/*
 * NAME: do_initialization
 *       This function initializes the data structues.
 *       It also collects initial set of values.
 *
 * RETURNS:
 * On successful completion:
 *   - returns 0.
 * In case of error
 *    - exits with code 1.
 */

int do_initialization(void)
{
    /* check how many perfstat_fcstat_t structures are available */
    if(collect_remote_node_stats) {
        strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
        nodeid.spec = NODENAME;
        tot = perfstat_fcstat_node(&nodeid, NULL, sizeof(perfstat_fcstat_t), 0);
    } else if(fc_flag == 1 && wwpn_flag == 1) {
        tot = perfstat_fcstat_wwpn(NULL, NULL, sizeof(perfstat_fcstat_t), 0);
        if(tot >= 1) {
           tot = 1;
        } else {
           printf("There is no FC adapter \n");
           exit(-1);
        }
    } else {
        tot = perfstat_fcstat(NULL, NULL, sizeof(perfstat_fcstat_t), 0);
    }

    if (tot <= 0) {
        printf("There is no FC adapter\n");
        exit(0);
    }

    /* allocate enough memory for all the structures */

    statp = (perfstat_fcstat_t *)malloc(tot * sizeof(perfstat_fcstat_t));
    CHECK_FOR_MALLOC_NULL(statp);

    statq = (perfstat_fcstat_t *)malloc(tot * sizeof(perfstat_fcstat_t));
    CHECK_FOR_MALLOC_NULL(statq);


    return(0);
}

/*
 *Name: display_metrics
 *       collect the metrics and display them
 *
 */
void display_metrics()
{
    perfstat_id_t first;
    perfstat_wwpn_id_t wwpn;
    int ret=0, i=0;

    if(collect_remote_node_stats) {
        strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
        nodeid.spec = NODENAME;

        strcpy(nodeid.name , FIRST_NETINTERFACE);
        ret = perfstat_fcstat_node(&nodeid, statq, sizeof(perfstat_fcstat_t), tot);
    } else if((fc_flag == 1) && (wwpn_flag == 1)) {
        strcpy(wwpn.name , fcadapter_name);
        wwpn.initiator_wwpn_name = wwpn_id;
        ret = perfstat_fcstat_wwpn( &wwpn, statq, sizeof(perfstat_fcstat_t), tot);
    } else {
        strcpy(first.name , FIRST_NETINTERFACE);
        ret = perfstat_fcstat( &first, statq, sizeof(perfstat_fcstat_t), tot);
    }

    if (ret < 0) {
        free(statp);
        free(statq);
        perror("perfstat_fcstat: ");
        exit(1);
    }

    while (count)
    {
        sleep (interval);

        if(collect_remote_node_stats) {
           ret = perfstat_fcstat_node(&nodeid, statp, sizeof(perfstat_fcstat_t), tot);
        } if((fc_flag == 1) && (wwpn_flag == 1)) {
           strcpy(wwpn.name , fcadapter_name);
           wwpn.initiator_wwpn_name = wwpn_id;
           ret = perfstat_fcstat_wwpn(&wwpn, statp, sizeof(perfstat_fcstat_t), tot);
        }  else {
           ret = perfstat_fcstat(&first, statp, sizeof(perfstat_fcstat_t), tot);
        }
        
       /* print statistics for each of the Fiber channel */
        for (i = 0; i < ret; i++) {
            printf(" FC Adapter name: %s \n",  statp[i].name);
            printf(" ======================== Traffic Statistics ============================\n");
            printf(" Number of Input Requests: %lld \n", statp[i].InputRequests - statq[i].InputRequests);
            printf(" Number of Output Requests: %lld \n",  statp[i].OutputRequests - statq[i].OutputRequests);
            printf(" Number of Input Bytes : %lld \n",  statp[i].InputBytes - statq[i].InputBytes);
            printf(" Number of Output Bytes : %lld \n",  statp[i].OutputBytes - statq[i].OutputBytes);
            printf(" ======================== Tranfer Statistics ============================\n");
            printf(" Adapter's Effective Maximum  Transfer Value  : %lld \n",  statp[i].EffMaxTransfer - statq[i].EffMaxTransfer);
            printf(" ======================== Driver Statistics ============================\n");            
            printf(" Count of DMA failures: %lld \n",  statp[i].NoDMAResourceCnt - statq[i].NoDMAResourceCnt);
            printf(" No command resource available :%lld \n", statp[i].NoCmdResourceCnt - statq[i].NoCmdResourceCnt);
            printf(" Link Indicator : %d \n", statp[i].AttentionType);
            printf(" ======================== CHBA Statistics ============================\n");                        
            printf(" Seconds since last reset of the statistics on the adapter: %lld \n", statp[i].SecondsSinceLastReset - statq[i].SecondsSinceLastReset);
            printf(" Number of frames transmitted: %lld \n", statp[i].TxFrames - statq[i].TxFrames);
            printf(" Fiber Channel Kbytes transmitted : %lld \n",statp[i].TxWords - statq[i].TxWords);
            printf(" Number of Frames Received.: %lld \n",statp[i].RxFrames - statq[i].RxFrames);
            printf(" Fiber Channel Kbytes Received : %lld \n",statp[i].RxWords - statq[i].RxWords);
            printf(" Loop Initialization Protocol(LIP) Count: %lld \n",statp[i].LIPCount - statq[i].LIPCount);
            printf(" NOS(Not_Operational) Count : %lld \n",statp[i].NOSCount - statq[i].NOSCount);
            printf(" Number of frames received with the CRC Error : %lld \n",statp[i].ErrorFrames - statq[i].ErrorFrames);
            printf(" Number of lost frames : %lld \n",statp[i].DumpedFrames - statq[i].DumpedFrames);
            printf(" Count of Link failures: %lld \n",statp[i].LinkFailureCount - statq[i].LinkFailureCount);
            printf(" Count of loss of sync : %lld \n",statp[i].LossofSyncCount - statq[i].LossofSyncCount);
            printf(" Count of loss of Signal:%lld \n",statp[i].LossofSignal - statq[i].LossofSignal);
            printf(" Number of times a primitive sequence was in error :%lld \n", statp[i].PrimitiveSeqProtocolErrCount - statq[i].PrimitiveSeqProtocolErrCount);
            printf(" Count of Invalid Transmission words received : %lld \n", statp[i].InvalidTxWordCount - statq[i].InvalidTxWordCount);
            printf(" Count of CRC Errors in a Received Frame :%lld \n", statp[i].InvalidCRCCount - statq[i].InvalidCRCCount);
            printf(" SCSI Id of the adapter : %lld \n", statp[i].PortFcId);
            printf(" Speed of Adapter in GBIT : %lld \n", statp[i].PortSpeed);
            printf(" Connection Tyoe: %s \n", statp[i].PortType);
            printf(" World Wide Port name : %lld \n",statp[i].PortWWN);
            printf(" Supported Port Speed in GBIT: %lld \n",statp[i].PortSupportedSpeed);
            
            printf(" ================================== End ==========================================\n");

        }

        memcpy(statq, statp, (tot * sizeof(perfstat_fcstat_t)));
        count--;
    }
}

/*
 *Name: main
 *
 */

int main(int argc, char *argv[])
{
    int i=0, rc=0;
    /* get the interval and count values */

    /* Process the arguments */
    while ((i = getopt(argc, argv, "i:c:n:a:w")) != EOF)
    {
        switch(i)
        {
           case 'i':               /* Interval */
                    interval = atoi(optarg);
                    if( interval <= 0 )
                        interval = INTERVAL_DEFAULT;
                    break;
           case 'c':               /* Number of interations */
                    count = atoi(optarg);
                    if( count <= 0 )
                        count = COUNT_DEFAULT;
                    break;
           case 'n':               /* Node name in a cluster environment */
                    strncpy(nodename, optarg, MAXHOSTNAMELEN);
                    nodename[MAXHOSTNAMELEN-1] = '\0';
                    collect_remote_node_stats = 1;
                    break;
           case 'a':    /* Fiber Chanel Adapter Name */ 
                    strncpy(fcadapter_name, optarg, MAXHOSTNAMELEN);
                    fcadapter_name[MAXHOSTNAMELEN-1] = '\0';
                    fc_flag = 1;
                    break; 
           case 'w':    /* Worl Wide Port Name(WWPN) */
                    wwpn_id = (unsigned long long) (atoll(optarg));
                    wwpn_flag = 1;
                    break;           
           default:
                   /* Invalid arguments. Print the usage and terminate */
                   showusage(argv[0]);
        }
    }

    if((fc_flag == 1))
    {
        if(fcadapter_name == NULL )
        {
            fprintf(stderr, "FC adapter Name  should not be NULL");
            exit(-1);
        }
    }

    if(wwpn_flag == 1)
    {
        if(wwpn_id < 0 )
        {
            fprintf(stderr, "WWPN id should not be negavite ");
            exit(-1);
        }        
    }

    if(collect_remote_node_stats)
    {   /* perfstat_config needs to be called to enable cluster statistics collection */
        rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
        if (rc == -1)
        {
            perror("cluster statistics collection is not available");
            exit(-1);
        }
    }

    do_initialization();
    display_metrics();

    if(collect_remote_node_stats)
    {   /* Now disable cluster statistics by calling perfstat_config */
        perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
    }
    free(statp);
    free(statq);
    return 0;
}

