/*  -*- Mode: C;  -*- */

/******************************************************************************
*                                                                             *
*   Copyright 2005 University of Cambridge Computer Laboratory.               *
*                                                                             *
*   This file is part of Nprobe.                                              *
*                                                                             *
*   Nprobe is free software; you can redistribute it and/or modify            *
*   it under the terms of the GNU General Public License as published by      *
*   the Free Software Foundation; either version 2 of the License, or         *
*   (at your option) any later version.                                       *
*                                                                             *
*   Nprobe is distributed in the hope that it will be useful,                 *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
*   GNU General Public License for more details.                              *
*                                                                             *
*   You should have received a copy of the GNU General Public License         *
*   along with Nprobe; if not, write to the Free Software                     *
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
*                                                                             *
******************************************************************************/


#ifndef _SUNDRY_RECORDS_H_
#define _SUNDRY_RECORDS_H_

/*
 * Structure to record sk_buff alloc fails
 */

struct sk_buff_alloc_fail_rec 
{
  struct timeval ts;
  int nfails;
};

typedef struct sk_buff_alloc_fail_rec sk_buff_alloc_fail_rec_t;


/*
 * Structure to record resource usage 
 */

struct np_rusage 
{
  struct timeval ts;
  struct rusage ru;
  struct rusage wru;		/* for the writer child */
  struct timeval wts;
  int spare[8];
};

typedef struct np_rusage np_rusage_t;


/*
 * Structure to record accounting period data 
 */

struct period_report 
{
  struct timeval ts;
  int buf_alloc_fails;
  unsigned int tous_in;
  unsigned int tous_out;
  unsigned int frus_in;
  unsigned int frus_out;
  double wire_mbs;
  unsigned int wire_pkts;
  double tcp_mbs;
  unsigned int tcp_pkts;
  double udp_mbs;
  unsigned int udp_pkts;
  double http_mbs;
  unsigned int http_pkts;
  double save_mBs;
  int buff_held;
  unsigned int rep_bytes_written;
  unsigned int nrecords;	
  unsigned int nrecords_tot;
  unsigned int dump_bytes_written;
  int tcp_to;
  int tcp_seq_to;
  int tcp_seq_to_forced;
  int tcp_seq_to_q;
  int tcp_seq_to_ack;
  int udp_to;
  unsigned int max_int_get;
  unsigned int min_tcp_seq_tp_f;
  ulonglong running_time;
  unsigned int max_fetch_interval;
  unsigned int html_parsed;		/* octs this period */
  unsigned int lag;			/* us lag behind wire driven stats */
  unsigned int repblks_dumped;
  unsigned int dumpblks_dumped;
  unsigned int IP_ulen_pkts;
  int nic_errs;
  int spare[1];
};

typedef struct period_report period_report_t; 

#ifndef SWIG_ONLY
/*
 * Structure to hold over accounting data between reports
 */
struct pr_save_last
{
  int started;
  struct timeval start;
  ulonglong wire_pkts, wire_octs;
  ulonglong tcp_pkts, tcp_octs;
  ulonglong udp_pkts, udp_octs;
  ulonglong http_pkts, http_octs;
  ulonglong html_pkts_parsed, html_octs_parsed;
  ulonglong  dump_bytes_written;
  ulonglong  rep_bytes_written;
  ulonglong  dump_blks_dumped;
  ulonglong  rep_blks_dumped;
  ulonglong  buf_alloc_fails;
  ulonglong IP_ulen_pkts;
};

typedef struct  pr_save_last  pr_save_last_t;

#endif /* ifndef SWIG_ONLY */

/* Reason for doing period report */
#define REP_CLOCK_DRIVEN 0
#define REP_WIRE_DRIVEN 1

/*
 * Macros and data-types for identifying CPU usage over fn calls
 */

struct ru_times 
{
  ulonglong utm;
  ulonglong stm;
};

typedef struct ru_times ru_times_t;

struct call_times 
{
  struct timeval ts;
  ru_times_t ip;
  ru_times_t tcp;
  ru_times_t tcp_inseq;
  ru_times_t tcp_catchup;
  ru_times_t tcp_serv;
  ru_times_t udp;
  ru_times_t http;
  ru_times_t html;
  ru_times_t spare[12];
};

typedef struct call_times call_times_t;


#ifdef TIME_CALLS_RUSAGE

extern call_times_t call_times;

#define GET_RUSAGE(where, rup) \
  MACRO_BEGIN \
    if (getrusage(RUSAGE_SELF, (rup)) != 0) \
      error((where), "getrusage"); \
  MACRO_END

#define TIME_NP_CALL(where, res, fn_and_args) \
  MACRO_BEGIN \
    struct rusage start; \
    struct rusage end; \
    long long uudiff, sudiff; \
    GET_RUSAGE((where), &start); \
    (fn_and_args); \
    GET_RUSAGE((where), &end); \
    uudiff = utvsub(&end.ru_utime, &start.ru_utime); \
    sudiff = utvsub(&end.ru_stime, &start.ru_stime); \
    (res)->utm += uudiff; \
    (res)->stm += sudiff; \
  MACRO_END

#define TIME_NP_CALL_RET(where, res, fn_and_args) \
  MACRO_BEGIN \
    struct rusage start; \
    struct rusage end; \
    long long uudiff, sudiff; \
    GET_RUSAGE((where), &start); \
    status = (fn_and_args); \
    GET_RUSAGE((where), &end); \
    uudiff = utvsub(&end.ru_utime, &start.ru_utime); \
    sudiff = utvsub(&end.ru_stime, &start.ru_stime); \
    (res)->utm += uudiff; \
    (res)->stm += sudiff; \
  MACRO_END

#endif /* ifdef TIME_CALLS_RUSAGE */

#ifdef NO_TIME_CALLS
#ifndef SWIG_ONLY

#define TIME_NP_CALL(where, res, fn_and_args) \
  MACRO_BEGIN \
    (fn_and_args); \
  MACRO_END

#define TIME_NP_CALL_RET(where, res, fn_and_args) \
  MACRO_BEGIN \
    status = (fn_and_args); \
  MACRO_END

#endif /* ifndef SWIG_ONLY */
#endif /* ifdef NO_TIME_CALLS */


/*
 * A 'temporary' record type - can hold other transient or expeimental types 
 * without making log file reads difficult when they change or disappear
 */

struct wrapper_record 
{
  int type;
  union 
  {
    long data[128];
    call_times_t call_times;
  } data;
};

typedef struct wrapper_record wrapper_record_t;

/* Types for wrapper records */
#define WRAPPER_EMPTY 0
#define WRAPPER_TIME_CALLS 1

/*
 * sundry_records.c 
 */

#ifdef PROBE_FED
#ifndef SWIG_ONLY

#define DO_RUSAGE 1
#define NO_RUSAGE 0
#define DO_PROCSTATS 1
#define NO_PROCSTATS 0

void record_buf_alloc_fails(struct timeval *ts, int nfails);
void record_rusage(struct timeval *ts, long long udiff);
void period_report(np_t *np, struct timeval *ts, long long udiff, 
		   unsigned int max_fetch_per, struct timeval *lastw_stats, 
		   int do_rusage, int do_procstats);
void dump_wrapper_rec(wrapper_record_t *recp);

#endif /* ifndef SWIG_ONLY */
#endif /* ifdef PROBE_FED */


#endif /* _SUNDRY_RECORDS_H_ */

/*
 * End sundry_records.h
 */
