/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/ccs/lib/libperfstat/simpleifstat.c 1.3.1.2          */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2008,2010              */
/* 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[] = "@(#)65        1.3.1.2  src/bos/usr/ccs/lib/libperfstat/simpleifstat.c, libperfstat, bos720 7/21/10 04:54:00";

/* The sample program display the metrics *
 * related to each and every Individual   * 
 * network interface in the LPAR          */

#include <stdio.h> 
#include <stdlib.h>
#include <libperfstat.h>
#include <net/if_types.h>
#include <wpars/wparcfg.h>

/* For WPAR, use NULL else use the actual WPAR ID (for global) */

#define WPAR_ID ((cid)?NULL:&wparid)

/* Non zero WPAR ID indicates WPAR */

#define IS_WPAR(X) ((X))

/* 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;
int returncode;

/* store the data structures */

static perfstat_netinterface_t *statp ,*statq;
static perfstat_netinterface_total_t *totalp, *totalq;
static perfstat_id_wpar_t wparid;
static perfstat_wpar_total_t wparinfo;

/* 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;

/*
 * 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> ]\n", cmd);
   exit(1);
}


/* 
 * NAME: decode 
 *       to determine the type of interface 
 *
 */

char * decode(uchar type) {

    switch(type) {

    case IFT_LOOP:
        return("loopback");

    case IFT_ISO88025:
        return("token-ring");

    case IFT_ETHER:
        return("ethernet");
    }

    return("other");
}

/*
 * 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_netinterface_t structures are available */
   if(collect_remote_node_stats) {
       strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
       nodeid.spec = NODENAME;
       tot = perfstat_netinterface_node(&nodeid, NULL, sizeof(perfstat_netinterface_t), 0);
   }
   else {
       tot = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0);
   }

   if (tot == 0) {
        printf("There is no net interface\n");
        exit(0);
   }
   if (tot < 0) {
        perror("perfstat_netinterface: ");
        exit(1);
   }
   
   /* allocate enough memory for all the structures */
    
   statp = (perfstat_netinterface_t *)malloc(tot * sizeof(perfstat_netinterface_t));
   CHECK_FOR_MALLOC_NULL(statp);

   statq = (perfstat_netinterface_t *)malloc(tot * sizeof(perfstat_netinterface_t));
   CHECK_FOR_MALLOC_NULL(statq);
   
   totalp = (perfstat_netinterface_total_t *) malloc(sizeof(perfstat_netinterface_total_t));
   CHECK_FOR_MALLOC_NULL(totalp);

   totalq = (perfstat_netinterface_total_t *) malloc(sizeof(perfstat_netinterface_total_t));
   CHECK_FOR_MALLOC_NULL(totalq);  
   
   return(0);
}

/*
 *Name: display_metrics
 *       collect the metrics and display them
 *
 */
void display_metrics()
{
    perfstat_id_t first;
    int ret, i;
	 	
   if(collect_remote_node_stats) {
       strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
       nodeid.spec = NODENAME;

       /*Retrieving the metrics of Global network interfaces*/
       if (perfstat_netinterface_total_node(&nodeid, totalq, sizeof(perfstat_netinterface_total_t), 1) < 0){
           perror("perfstat_netinterface_total_node :");
           exit(1);
       }
       strcpy(nodeid.name , FIRST_NETINTERFACE);
       ret = perfstat_netinterface_node(&nodeid, statq, sizeof(perfstat_netinterface_t), tot);
   }
   else {
       /*Retrieving the metrics of Global network interfaces*/
       if (perfstat_netinterface_total( NULL, totalq, sizeof(perfstat_netinterface_total_t), 1) < 0){
           perror("perfstat_netinterface_total :");
           exit(1);
       }
       strcpy(first.name , FIRST_NETINTERFACE);
       ret = perfstat_netinterface( &first, statq, sizeof(perfstat_netinterface_t), tot);
   }

    if (ret < 0) {
        perror("perfstat_netinterface: ");
        exit(1);
    }

    /*
     * Name    - name of the netinterface
     * Type    - type of the interface
     * Ipackets- number of input packets
     * Ierrors - number of input errors
     * Ibytes  - number of input bytes
     * Opackets- number of output packets
     * Oerrors - number of output errors
     * Obytes  - number of output bytes
     *
     */
 
    printf("\n%6s %10s %10s %10s %10s %10s %10s %10s\n", " Name ", " Type ", " Ipackets ", " Ierrors ", 
							 " Ibytes "," Opackets "," Oerrors "," Obytes ");
    printf("%6s %10s %10s %10s %10s %10s %10s %10s\n", "======", "======", "=========", "=========",
						       "========","=========","=========","========");

    while (count)
    {
       sleep (interval);
     
       /* get the total netinterface structure */
       if(collect_remote_node_stats) {
           if (perfstat_netinterface_total_node(&nodeid, totalp, sizeof(perfstat_netinterface_total_t), 1) < 0){
               perror("perfstat_netinterface_total :");
               exit(1);
           }
       }
       else {
           if (perfstat_netinterface_total( NULL, totalp, sizeof(perfstat_netinterface_total_t), 1) < 0){
               perror("perfstat_netinterface_total :");
               exit(1);
           }
       }

       printf("%6s %10s %10llu %10llu %10llu %10llu %10llu %10llu\n","total", "  ", (totalp->ipackets - totalq->ipackets),
					(totalp->ierrors - totalq->ierrors), (totalp->ibytes - totalq->ibytes),
					(totalp->opackets - totalq->opackets), (totalp->oerrors - totalq->oerrors),
				        (totalp->obytes - totalq->obytes));

       /* ask to get all the structures available in one call */
       /* return code is number of structures returned */
   
       if(collect_remote_node_stats) {
           ret = perfstat_netinterface_node(&nodeid, statp, sizeof(perfstat_netinterface_t), tot);
       }
       else {
           ret = perfstat_netinterface(&first, statp, sizeof(perfstat_netinterface_t), tot);
       }

       /* print statistics for each of the interfaces */
       for (i = 0; i < ret; i++) {
            printf("%6s %10s %10llu %10llu %10llu %10llu %10llu %10llu\n", statp[i].name, decode(statp[i].type), 
					(statp[i].ipackets - statq[i].ipackets), (statp[i].ierrors - statq[i].ierrors), 
					(statp[i].ibytes - statq[i].ibytes), (statp[i].opackets - statq[i].opackets), 
					(statp[i].oerrors - statq[i].oerrors), (statp[i].obytes - statq[i].obytes ));
       }
      
       memcpy(totalq, totalp, sizeof(perfstat_netinterface_total_t));
       memcpy(statq, statp, (tot * sizeof(perfstat_netinterface_t)));
       count--;
    }
}

/* 
 *Name: main 
 *
 */

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

   /* Process the arguments */
   while ((i = getopt(argc, argv, "i:c:n:")) != 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;
           default:
                   /* Invalid arguments. Print the usage and terminate */
                   showusage(argv[0]);
       }
   }

   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);
   }
}

