* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include <stdio.h>
#include "globals.h"
#define CALC_TYPE_FRAMES 0
-#define CALC_TYPE_BYTES 1
-#define CALC_TYPE_FRAMES_AND_BYTES 2
-#define CALC_TYPE_COUNT 3
-#define CALC_TYPE_SUM 4
-#define CALC_TYPE_MIN 5
-#define CALC_TYPE_MAX 6
-#define CALC_TYPE_AVG 7
-#define CALC_TYPE_LOAD 8
+#define CALC_TYPE_BYTES 1
+#define CALC_TYPE_FRAMES_AND_BYTES 2
+#define CALC_TYPE_COUNT 3
+#define CALC_TYPE_SUM 4
+#define CALC_TYPE_MIN 5
+#define CALC_TYPE_MAX 6
+#define CALC_TYPE_AVG 7
+#define CALC_TYPE_LOAD 8
typedef struct {
const char *func_name;
typedef struct _io_stat_t {
guint64 interval; /* The user-specified time interval (us) */
guint invl_prec; /* Decimal precision of the time interval (1=10s, 2=100s etc) */
- guint32 num_cols; /* The number of columns of statistics in the table */
+ int num_cols; /* The number of columns of stats in the table */
struct _io_stat_item_t *items; /* Each item is a single cell in the table */
time_t start_time; /* Time of first frame matching the filter */
const char **filters; /* 'io,stat' cmd strings (e.g., "AVG(smb.time)smb.time") */
gdouble double_counter;
} io_stat_item_t;
-#define NANOSECS_PER_SEC 1000000000
+#define NANOSECS_PER_SEC 1000000000ULL
+
+static guint64 last_relative_time;
static int
iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_)
GPtrArray *gp;
guint i;
int ftype;
-
+
mit = (io_stat_item_t *) arg;
parent = mit->parent;
- relative_time = (guint64)((pinfo->fd->rel_ts.secs*1000000) + ((pinfo->fd->rel_ts.nsecs+500)/1000));
+
+ /* If this frame's relative time is negative, set its relative time to last_relative_time
+ rather than disincluding it from the calculations. */
+ if (pinfo->rel_ts.secs >= 0) {
+ relative_time = ((guint64)pinfo->rel_ts.secs * 1000000ULL) +
+ ((guint64)((pinfo->rel_ts.nsecs+500)/1000));
+ last_relative_time = relative_time;
+ } else {
+ relative_time = last_relative_time;
+ }
+
if (mit->parent->start_time == 0) {
- mit->parent->start_time = pinfo->fd->abs_ts.secs - pinfo->fd->rel_ts.secs;
+ mit->parent->start_time = pinfo->fd->abs_ts.secs - pinfo->rel_ts.secs;
}
- /* The prev item before the main one is always the last interval we saw packets for */
+ /* The prev item is always the last interval in which we saw packets. */
it = mit->prev;
- /* XXX for the time being, just ignore all frames that are in the past.
- should be fixed in the future but hopefully it is uncommon */
- if(relative_time < it->time){
- return FALSE;
- }
-
/* If we have moved into a new interval (row), create a new io_stat_item_t struct for every interval
- * between the last struct and this one. If an item was not found in a previous interval, an empty
+ * between the last struct and this one. If an item was not found in a previous interval, an empty
* struct will be created for it. */
rt = relative_time;
while (rt >= it->time + parent->interval) {
it->counter += (gint64)fvalue_get_integer64(&((field_info *)gp->pdata[i])->value);
break;
case FT_FLOAT:
- it->float_counter +=
+ it->float_counter +=
(gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
break;
case FT_DOUBLE:
it->double_counter += fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
break;
case FT_RELATIVE_TIME:
- new_time = fvalue_get(&((field_info *)gp->pdata[i])->value);
- val = (guint64)((new_time->secs * NANOSECS_PER_SEC) + new_time->nsecs);
+ new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
+ val = ((guint64)new_time->secs * NANOSECS_PER_SEC) + (guint64)new_time->nsecs;
it->counter += val;
break;
default:
val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value);
if((it->frames==1 && i==0) || ((gint64)val < (gint64)it->counter)) {
it->counter=val;
- }
+ }
break;
case FT_FLOAT:
float_val=(gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
double_val=fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
if((it->frames==1 && i==0) || (double_val < it->double_counter)) {
it->double_counter=double_val;
- }
+ }
break;
case FT_RELATIVE_TIME:
new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
- val = (guint64)new_time->secs * NANOSECS_PER_SEC + new_time->nsecs;
+ val = ((guint64)new_time->secs * NANOSECS_PER_SEC) + (guint64)new_time->nsecs;
if((it->frames==1 && i==0) || (val < it->counter)) {
it->counter=val;
}
break;
case FT_UINT64:
val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value);
- if(val > it->counter)
+ if(val > it->counter)
it->counter=val;
break;
case FT_INT8:
case FT_INT24:
case FT_INT32:
val = fvalue_get_sinteger(&((field_info *)gp->pdata[i])->value);
- if((gint32)val > (gint32)it->counter)
+ if((gint32)val > (gint32)it->counter)
it->counter=val;
break;
case FT_INT64:
val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value);
- if ((gint64)val > (gint64)it->counter)
+ if ((gint64)val > (gint64)it->counter)
it->counter=val;
break;
case FT_FLOAT:
break;
case FT_RELATIVE_TIME:
new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
- val = (guint64)((new_time->secs * NANOSECS_PER_SEC) + new_time->nsecs);
+ val = ((guint64)new_time->secs * NANOSECS_PER_SEC) + (guint64)new_time->nsecs;
if (val>it->counter)
it->counter=val;
break;
gp=proto_get_finfo_ptr_array(edt->tree, it->hf_index);
if(gp){
guint64 val;
-
+
ftype=proto_registrar_get_ftype(it->hf_index);
for(i=0;i<gp->len;i++){
it->num++;
break;
case FT_RELATIVE_TIME:
new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
- val = (guint64)((new_time->secs * NANOSECS_PER_SEC) + new_time->nsecs);
+ val = ((guint64)new_time->secs * NANOSECS_PER_SEC) + (guint64)new_time->nsecs;
it->counter += val;
break;
default:
io_stat_item_t *pit;
new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
- val = (guint64)((new_time->secs*1000000) + (new_time->nsecs/1000));
+ val = ((guint64)new_time->secs*1000000ULL) + (guint64)(new_time->nsecs/1000);
tival = (int)(val % parent->interval);
it->counter += tival;
val -= tival;
}
break;
}
- /* Store the highest value for this item in order to determine the width of each stat column.
+ /* Store the highest value for this item in order to determine the width of each stat column.
* For real numbers we only need to know its magnitude (the value to the left of the decimal point
* so round it up before storing it as an integer in max_vals. For AVG of RELATIVE_TIME fields,
* calc the average, round it to the next second and store the seconds. For all other calc types
- * of RELATIVE_TIME fields, store the counters without modification.
+ * of RELATIVE_TIME fields, store the counters without modification.
* fields. */
switch(it->calc_type) {
case CALC_TYPE_FRAMES:
case CALC_TYPE_FRAMES_AND_BYTES:
- parent->max_frame[it->colnum] =
+ parent->max_frame[it->colnum] =
MAX(parent->max_frame[it->colnum], it->frames);
if (it->calc_type==CALC_TYPE_FRAMES_AND_BYTES)
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum], it->counter);
-
+
case CALC_TYPE_BYTES:
case CALC_TYPE_COUNT:
case CALC_TYPE_LOAD:
ftype=proto_registrar_get_ftype(it->hf_index);
switch(ftype) {
case FT_FLOAT:
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum], (guint64)(it->float_counter+0.5));
break;
case FT_DOUBLE:
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum],(guint64)(it->double_counter+0.5));
break;
case FT_RELATIVE_TIME:
- parent->max_vals[it->colnum] =
- MAX(parent->max_vals[it->colnum], it->counter);
- break;
+ parent->max_vals[it->colnum] =
+ MAX(parent->max_vals[it->colnum], it->counter);
+ break;
default:
/* UINT16-64 and INT8-64 */
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum], it->counter);
break;
}
ftype=proto_registrar_get_ftype(it->hf_index);
switch(ftype) {
case FT_FLOAT:
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum], (guint64)it->float_counter/it->num);
break;
case FT_DOUBLE:
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum],(guint64)it->double_counter/it->num);
break;
case FT_RELATIVE_TIME:
- parent->max_vals[it->colnum] =
- MAX(parent->max_vals[it->colnum], ((it->counter/it->num) + 500000000) / NANOSECS_PER_SEC);
+ parent->max_vals[it->colnum] =
+ MAX(parent->max_vals[it->colnum], ((it->counter/(guint64)it->num) + 500000000ULL) / NANOSECS_PER_SEC);
break;
default:
/* UINT16-64 and INT8-64 */
- parent->max_vals[it->colnum] =
+ parent->max_vals[it->colnum] =
MAX(parent->max_vals[it->colnum], it->counter/it->num);
break;
}
return TRUE;
}
-static int
+static int
magnitude (guint64 val, int max_w)
{
int i, mag=0;
for (i=0; i<max_w; i++) {
mag++;
- if ((val /= 10)==0)
- break;
+ if ((val /= 10)==0)
+ break;
}
return(mag);
}
-/*
-* Print the calc_type_table[] function label centered in the column header.
+/*
+* Print the calc_type_table[] function label centered in the column header.
*/
static void
printcenter (const char *label, int lenval, int numpad)
len = (int) (strlen(spaces)) - (((lenval-lenlab) / 2) + numpad);
if (len > 0 && len < 6) {
- spaces_ptr = &spaces[len];
+ spaces_ptr = &spaces[len];
if ((lenval-lenlab)%2==0) {
printf("%s%s%s|", spaces_ptr, label, spaces_ptr);
} else {
- printf("%s%s%s|", spaces_ptr-1, label, spaces_ptr);
+ printf("%s%s%s|", spaces_ptr-1, label, spaces_ptr);
}
} else if (len > 0 && len <= 15) {
printf("%s|", label);
iostat_draw(void *arg)
{
guint32 num;
- guint64 interval, duration, t, invl_end;
- int i, j, k, num_cols, num_rows, dv, dur_secs, dur_mag, invl_mag, invl_prec, tabrow_w,
- borderlen, invl_col_w, numpad=1, namelen, len_filt, type, maxfltr_w, ftype;
+ guint64 interval, duration, t, invl_end, dv;
+ int i, j, k, num_cols, num_rows, dur_secs_orig, dur_nsecs_orig, dur_secs, dur_nsecs, dur_mag,
+ invl_mag, invl_prec, tabrow_w, borderlen, invl_col_w, numpad=1, namelen, len_filt, type,
+ maxfltr_w, ftype;
int fr_mag; /* The magnitude of the max frame number in this column */
int val_mag; /* The magnitude of the max value in this column */
char *spaces, *spaces_s, *filler_s=NULL, **fmts, *fmt=NULL;
const char *filter;
- static gchar dur_mag_s[3], invl_mag_s[3], invl_prec_s[3], fr_mag_s[3], val_mag_s[3], *invl_fmt, *full_fmt;
+ static gchar dur_mag_s[3], invl_prec_s[3], fr_mag_s[3], val_mag_s[3], *invl_fmt, *full_fmt;
io_stat_item_t *mit, **stat_cols, *item, **item_in_column;
gboolean last_row=FALSE;
io_stat_t *iot;
- column_width *col_w;
+ column_width *col_w;
struct tm * tm_time;
time_t the_time;
num_cols = iot->num_cols;
col_w = (column_width *)g_malloc(sizeof(column_width) * num_cols);
fmts = (char **)g_malloc(sizeof(char *) * num_cols);
- duration = (guint64)((cfile.elapsed_time.secs*1000000) + ((cfile.elapsed_time.nsecs+500)/1000));
+ duration = ((guint64)cfile.elapsed_time.secs * 1000000ULL) +
+ (guint64)((cfile.elapsed_time.nsecs + 500) / 1000);
/* Store the pointer to each stat column */
stat_cols = (io_stat_item_t **) g_malloc(sizeof(io_stat_item_t *) * num_cols);
}
/* Calc the capture duration's magnitude (dur_mag) */
- dur_secs = (int)duration/1000000;
+ dur_secs = (int)(duration/1000000ULL);
+ dur_secs_orig = dur_secs;
+ dur_nsecs = (int)(duration%1000000ULL);
+ dur_nsecs_orig = dur_nsecs;
dur_mag = magnitude((guint64)dur_secs, 5);
- g_snprintf(dur_mag_s, 3, "%u", dur_mag);
+ g_snprintf(dur_mag_s, 3, "%u", dur_mag);
/* Calc the interval's magnitude */
- invl_mag = magnitude((guint64)interval/1000000, 5);
+ invl_mag = magnitude(interval/1000000ULL, 5);
/* Set or get the interval precision */
if (interval==duration) {
- /*
+ /*
* An interval arg of 0 or an interval size exceeding the capture duration was specified.
* Set the decimal precision of duration based on its magnitude. */
if (dur_mag >= 2)
invl_prec = 1;
- else if (dur_mag==1)
+ else if (dur_mag==1)
invl_prec = 3;
else
invl_prec = 6;
dv=1000000;
for (i=0; i<invl_prec; i++)
dv /= 10;
- duration = duration + (5*(dv/10));
- if (iot->interval==G_MAXINT32)
+ if ((duration%dv) > 5*(dv/10)) {
+ duration += 5*(dv/10);
+ duration = (duration/dv) * dv;
+ dur_secs = (int)(duration/1000000ULL);
+ dur_nsecs = (int)(duration%1000000ULL);
+ /*
+ * Recalc dur_mag in case rounding has increased its magnitude */
+ dur_mag = magnitude((guint64)dur_secs, 5);
+ }
+ if (iot->interval==G_MAXINT32)
interval = duration;
- /* Recalc the dur_mag in case rounding has increased its magnitude */
- dur_secs = (int)duration/1000000;
- dur_mag = magnitude((guint64)dur_secs, 5);
-
/* Calc the width of the time interval column (incl borders and padding). */
- if (invl_prec==0)
+ if (invl_prec==0)
invl_col_w = (2*dur_mag) + 8;
else
invl_col_w = (2*dur_mag) + (2*invl_prec) + 10;
- /* Update the width of the time interval column (in fact the date) */
- switch (timestamp_get_type()) {
- case TS_ABSOLUTE:
- invl_col_w=12;
- break;
- case TS_ABSOLUTE_WITH_DATE:
- invl_col_w=23;
- break;
- default:
- break;
- }
- invl_col_w = MAX(invl_col_w, 12);
+ /* Update the width of the time interval column for "-t ad" */
+ if (timestamp_get_type()==TS_ABSOLUTE_WITH_DATE)
+ invl_col_w = MAX(invl_col_w, 23);
+ else
+ invl_col_w = MAX(invl_col_w, 12);
+
borderlen = MAX(borderlen, invl_col_w);
/* Calc the total width of each row in the stats table and build the printf format string for each
g_snprintf(fr_mag_s, 3, "%u", fr_mag);
if (type==CALC_TYPE_FRAMES) {
- fmt = g_strconcat(" %", fr_mag_s, "u |", NULL);
- } else {
- /* CALC_TYPE_FRAMES_AND_BYTES
+ fmt = g_strconcat(" %", fr_mag_s, "u |", NULL);
+ } else {
+ /* CALC_TYPE_FRAMES_AND_BYTES
*/
val_mag = magnitude(iot->max_vals[j], 15);
val_mag = MAX(5, val_mag);
g_snprintf(val_mag_s, 3, "%u", val_mag);
fmt = g_strconcat(" %", val_mag_s, G_GINT64_MODIFIER, "u |", NULL);
break;
-
+
default:
ftype = proto_registrar_get_ftype(stat_cols[j]->hf_index);
- switch (ftype) {
+ switch (ftype) {
case FT_FLOAT:
case FT_DOUBLE:
val_mag = magnitude(iot->max_vals[j], 15);
col_w[j].val = val_mag + 7;
break;
case FT_RELATIVE_TIME:
- /* Convert FT_RELATIVE_TIME field to seconds
+ /* Convert FT_RELATIVE_TIME field to seconds
* CALC_TYPE_LOAD was already converted in iostat_packet() ) */
if (type==CALC_TYPE_LOAD) {
iot->max_vals[j] /= interval;
- } else {
- iot->max_vals[j] = (iot->max_vals[j] + 500000000) / NANOSECS_PER_SEC;
+ } else if (type != CALC_TYPE_AVG) {
+ iot->max_vals[j] = (iot->max_vals[j] + 500000000ULL) / NANOSECS_PER_SEC;
}
val_mag = magnitude(iot->max_vals[j], 15);
g_snprintf(val_mag_s, 3, "%u", val_mag);
fmt = g_strconcat(" %", val_mag_s, "u.%06u |", NULL);
col_w[j].val = val_mag + 7;
- break;
-
+ break;
+
default:
val_mag = magnitude(iot->max_vals[j], 15);
val_mag = MAX(namelen, val_mag);
col_w[j].val = val_mag;
g_snprintf(val_mag_s, 3, "%u", val_mag);
-
+
switch (ftype) {
case FT_UINT8:
case FT_UINT16:
case FT_UINT32:
case FT_UINT64:
fmt = g_strconcat(" %", val_mag_s, G_GINT64_MODIFIER, "u |", NULL);
- break;
+ break;
case FT_INT8:
case FT_INT16:
case FT_INT24:
} /* End of ftype switch */
} /* End of calc_type switch */
tabrow_w += col_w[j].val + 3;
- if (fmt)
+ if (fmt)
fmts[j] = fmt;
} /* End of for loop (columns) */
- borderlen = MAX(borderlen, tabrow_w);
+ borderlen = MAX(borderlen, tabrow_w);
/* Calc the max width of the list of filters. */
maxfltr_w = 0;
/* The stat table is not wrapped (by tshark) but filter is wrapped at the width of the stats table
* (which currently = borderlen); however, if the filter width exceeds the table width and the
* table width is less than 102 bytes, set borderlen to the lesser of the max filter width and 102.
- * The filters will wrap at the lesser of borderlen-2 and the last space in the filter.
+ * The filters will wrap at the lesser of borderlen-2 and the last space in the filter.
* NOTE: 102 is the typical size of a user window when the font is fixed width (e.g., COURIER 10).
* XXX: A pref could be added to change the max width from the default size of 102. */
if (maxfltr_w > borderlen && borderlen < 102)
/* Prevent double right border by adding a space */
if (borderlen-tabrow_w==1)
- borderlen++;
+ borderlen++;
/* Display the top border */
printf("\n");
for (i=0; i<borderlen; i++)
printf("=");
-
+
spaces = (char*) g_malloc(borderlen+1);
- for (i=0; i<borderlen; i++)
+ for (i=0; i<borderlen; i++)
spaces[i] = ' ';
spaces[borderlen] = '\0';
-
+
spaces_s = &spaces[16];
printf("\n| IO Statistics%s|\n", spaces_s);
spaces_s = &spaces[2];
printf("|%s|\n", spaces_s);
-
- g_snprintf(invl_mag_s, 3, "%u", invl_mag);
- if (invl_prec > 0) {
- g_snprintf(invl_prec_s, 3, "%u", invl_prec);
- invl_fmt = g_strconcat("%", invl_mag_s, "u.%0", invl_prec_s, "u", NULL);
- if (interval==duration) {
- full_fmt = g_strconcat("| Interval size: ", invl_fmt, " secs (dur)%s", NULL);
- spaces_s = &spaces[30+invl_mag+invl_prec];
- } else {
- full_fmt = g_strconcat("| Interval size: ", invl_fmt, " secs%s", NULL);
- spaces_s = &spaces[24+invl_mag+invl_prec];
- }
- printf(full_fmt, (guint32)interval/1000000,
- (guint32)((interval%1000000)/dv), spaces_s);
+
+ if (invl_prec==0) {
+ invl_fmt = g_strconcat("%", dur_mag_s, "u", NULL);
+ full_fmt = g_strconcat("| Duration: ", invl_fmt, ".%6u secs%s|\n", NULL);
+ spaces_s = &spaces[25 + dur_mag];
+ printf(full_fmt, dur_secs_orig, dur_nsecs_orig, spaces_s);
+ g_free(full_fmt);
+ full_fmt = g_strconcat("| Interval: ", invl_fmt, " secs%s|\n", NULL);
+ spaces_s = &spaces[18 + dur_mag];
+ printf(full_fmt, (guint32)(interval/1000000ULL), spaces_s);
} else {
- invl_fmt = g_strconcat("%", invl_mag_s, "u", NULL);
- full_fmt = g_strconcat("| Interval size: ", invl_fmt, " secs%s", NULL);
- spaces_s = &spaces[23 + invl_mag];
- printf(full_fmt, (guint32)interval/1000000, spaces_s);
+ g_snprintf(invl_prec_s, 3, "%u", invl_prec);
+ invl_fmt = g_strconcat("%", dur_mag_s, "u.%0", invl_prec_s, "u", NULL);
+ full_fmt = g_strconcat("| Duration: ", invl_fmt, " secs%s|\n", NULL);
+ spaces_s = &spaces[19 + dur_mag + invl_prec];
+ printf(full_fmt, dur_secs, dur_nsecs/(int)dv, spaces_s);
+ g_free(full_fmt);
+
+ full_fmt = g_strconcat("| Interval: ", invl_fmt, " secs%s|\n", NULL);
+ spaces_s = &spaces[19 + dur_mag + invl_prec];
+ printf(full_fmt, (guint32)(interval/1000000ULL),
+ (guint32)((interval%1000000ULL)/dv), spaces_s);
}
- g_free(invl_fmt);
g_free(full_fmt);
- if (invl_prec > 0)
- invl_fmt = g_strconcat("%", dur_mag_s, "u.%0", invl_prec_s, "u", NULL);
- else
- invl_fmt = g_strconcat("%", dur_mag_s, "u", NULL);
-
+ spaces_s = &spaces[2];
+ printf("|%s|\n", spaces_s);
+
/* Display the list of filters and their column numbers vertically */
- printf("|\n| Col");
+ printf("| Col");
for(j=0; j<num_cols; j++){
printf((j==0 ? "%2u: " : "| %2u: "), j+1);
- if (!iot->filters[j] || (iot->filters[j]==0)) {
- /*
+ if (!iot->filters[j] || (iot->filters[j]==0)) {
+ /*
* An empty (no filter) comma field was specified */
spaces_s = &spaces[16 + 10];
printf("Frames and bytes%s|\n", spaces_s);
} else {
filter = iot->filters[j];
len_filt = (int) strlen(filter);
-
+
/* If the width of the widest filter exceeds the width of the stat table, borderlen has
* been set to 102 bytes above and filters wider than 102 will wrap at 91 bytes. */
if (len_filt+11 <= borderlen) {
const gchar *pos;
gsize len;
int next_start, max_w=borderlen-11;
-
+
do {
if (len_filt > max_w) {
sfilter1 = g_strndup( (gchar *) filter, (gsize) max_w);
- /*
+ /*
* Find the pos of the last space in sfilter1. If a space is found, set
* sfilter2 to the string prior to that space and print it; otherwise, wrap
* the filter at max_w. */
printf("%s%s|\n", filter, &spaces[((int)strlen(filter))+10]);
break;
}
- } while (1);
+ } while (1);
}
}
}
for(j=0; j<num_cols; j++) {
item = stat_cols[j];
if(item->calc_type==CALC_TYPE_FRAMES_AND_BYTES)
- spaces_s = &spaces[borderlen - (col_w[j].fr + col_w[j].val)] - 3;
+ spaces_s = &spaces[borderlen - (col_w[j].fr + col_w[j].val)] - 3;
else if (item->calc_type==CALC_TYPE_FRAMES)
- spaces_s = &spaces[borderlen - col_w[j].fr];
+ spaces_s = &spaces[borderlen - col_w[j].fr];
else
- spaces_s = &spaces[borderlen - col_w[j].val];
+ spaces_s = &spaces[borderlen - col_w[j].val];
printf("%-2u%s|", j+1, spaces_s);
}
filler_s = &spaces[tabrow_w+1];
printf("%s|", filler_s);
}
-
- printf("\n| Interval");
+
+ k = 11;
switch (timestamp_get_type()) {
case TS_ABSOLUTE:
- printf("\n| Time ");
- break;
+ printf("\n| Time ");
+ break;
case TS_ABSOLUTE_WITH_DATE:
- printf("\n| Date ");
- break;
+ printf("\n| Date and time");
+ k = 16;
+ break;
case TS_RELATIVE:
case TS_NOT_SET:
- printf("\n| Interval");
- break;
+ printf("\n| Interval");
+ break;
default:
- break;
+ break;
}
- spaces_s = &spaces[borderlen-(invl_col_w-11)];
+ spaces_s = &spaces[borderlen-(invl_col_w-k)];
printf("%s|", spaces_s);
/* Display the stat label in each column */
printf("\n");
t=0;
- full_fmt = g_strconcat("| ", invl_fmt, " <> ", invl_fmt, " |", NULL);
- num_rows = (int)(duration/interval) + (((duration%interval+500000)/1000000) > 0 ? 1 : 0);
+ if (invl_prec==0 && dur_mag==1)
+ full_fmt = g_strconcat("| ", invl_fmt, " <> ", invl_fmt, " |", NULL);
+ else
+ full_fmt = g_strconcat("| ", invl_fmt, " <> ", invl_fmt, " |", NULL);
+
+ if (interval == 0 || duration == 0) {
+ num_rows = 0;
+ } else {
+ num_rows = (int)(duration/interval) + ((int)(duration%interval) > 0 ? 1 : 0);
+ }
/* Load item_in_column with the first item in each column */
- item_in_column = (io_stat_item_t **) g_malloc(sizeof(io_stat_item_t) * num_cols);
+ item_in_column = (io_stat_item_t **) g_malloc(sizeof(io_stat_item_t *) * num_cols);
for (j=0; j<num_cols; j++) {
item_in_column[j] = stat_cols[j];
}
- /* Display the table values
+ /* Display the table values
*
* The outer loop is for time interval rows and the inner loop is for stat column items.*/
for (i=0; i<num_rows; i++) {
}
/* Patch for Absolute Time */
- the_time=iot->start_time+(guint32)(t/1000000);
+ /* XXX - has a Y2.038K problem with 32-bit time_t */
+ the_time = (time_t)(iot->start_time + (t/1000000ULL));
tm_time = localtime(&the_time);
/* Display the interval for this row */
- switch (timestamp_get_type()) {
+ switch (timestamp_get_type()) {
case TS_ABSOLUTE:
printf("| %02d:%02d:%02d |",
tm_time->tm_hour,
tm_time->tm_min,
tm_time->tm_sec);
break;
-
+
case TS_ABSOLUTE_WITH_DATE:
printf("| %04d-%02d-%02d %02d:%02d:%02d |",
tm_time->tm_year + 1900,
tm_time->tm_min,
tm_time->tm_sec);
break;
-
+
case TS_RELATIVE:
case TS_NOT_SET:
if (invl_prec==0) {
- printf(full_fmt, (guint32)(t/1000000),
- (guint32)(invl_end/1000000));
+ if(last_row) {
+ int maxw;
+ maxw = dur_mag >= 3 ? dur_mag+1 : 3;
+ g_free(full_fmt);
+ g_snprintf(dur_mag_s, 3, "%u", maxw);
+ full_fmt = g_strconcat( dur_mag==1 ? "| " : "| ",
+ invl_fmt, " <> ", "%-",
+ dur_mag_s, "s|", NULL);
+ printf(full_fmt, (guint32)(t/1000000ULL), "Dur");
+ } else {
+ printf(full_fmt, (guint32)(t/1000000ULL),
+ (guint32)(invl_end/1000000ULL));
+ }
} else {
- printf(full_fmt, (guint32)(t/1000000),
- (guint32)(t%1000000) / dv,
- (guint32) (invl_end/1000000),
- (guint32)((invl_end%1000000) / dv));
+ printf(full_fmt, (guint32)(t/1000000ULL),
+ (guint32)(t%1000000ULL / dv),
+ (guint32)(invl_end/1000000ULL),
+ (guint32)(invl_end%1000000ULL / dv));
}
break;
/* case TS_DELTA:
/* Display stat values in each column for this row */
for (j=0; j<num_cols; j++) {
fmt = fmts[j];
- item = item_in_column[j];
+ item = item_in_column[j];
if (item) {
switch(item->calc_type) {
printf(fmt, item->double_counter);
break;
case FT_RELATIVE_TIME:
- item->counter = (item->counter + 500) / 1000;
- printf(fmt, (int)(item->counter/1000000), (int)(item->counter%1000000));
+ item->counter = (item->counter + 500ULL) / 1000ULL;
+ printf(fmt, (int)(item->counter/1000000ULL), (int)(item->counter%1000000ULL));
break;
default:
printf(fmt, item->counter);
printf(fmt, item->double_counter/num);
break;
case FT_RELATIVE_TIME:
- item->counter = ((item->counter/num) + 500) / 1000;
+ item->counter = ((item->counter / (guint64)num) + 500ULL) / 1000ULL;
printf(fmt,
- (int)(item->counter/1000000), (int)(item->counter%1000000));
+ (int)(item->counter/1000000ULL), (int)(item->counter%1000000ULL));
break;
default:
- printf(fmt, item->counter/num);
+ printf(fmt, item->counter / (guint64)num);
break;
}
break;
case FT_RELATIVE_TIME:
if (!last_row) {
printf(fmt,
- (int) (item->counter/interval),
- (int)((item->counter%interval)*1000000 / interval));
+ (int) (item->counter/interval),
+ (int)((item->counter%interval)*1000000ULL / interval));
} else {
printf(fmt,
(int) (item->counter/(invl_end-t)),
- (int)((item->counter%(invl_end-t))*1000000 / (invl_end-t)));
+ (int)((item->counter%(invl_end-t))*1000000ULL / (invl_end-t)));
}
break;
}
if (fmt)
g_free(fmt);
} else {
- item_in_column[j] = item_in_column[j]->next;
+ item_in_column[j] = item_in_column[j]->next;
}
} else {
- printf(fmt, (guint64)0);
+ printf(fmt, (guint64)0, (guint64)0);
}
}
if (filler_s)
printf("%s|", filler_s);
printf("\n");
t += interval;
-
+
}
for(i=0;i<borderlen;i++){
printf("=");
p=filter+namelen+1;
parenp=strchr(p, ')');
if(!parenp){
- fprintf(stderr,
+ fprintf(stderr,
"\ntshark: Closing parenthesis missing from calculated expression.\n");
exit(10);
}
if(io->items[i].calc_type==CALC_TYPE_FRAMES || io->items[i].calc_type==CALC_TYPE_BYTES){
if(parenp!=p) {
- fprintf(stderr,
+ fprintf(stderr,
"\ntshark: %s does not require or allow a field name within the parens.\n",
calc_type_table[j].func_name);
exit(10);
}
static void
-iostat_init(const char *optarg, void* userdata _U_)
+iostat_init(const char *opt_arg, void* userdata _U_)
{
gdouble interval_float;
- guint32 idx=0, i;
+ guint32 idx=0;
+ int i;
io_stat_t *io;
- const gchar *filters=NULL, *str, *pos;
+ const gchar *filters, *str, *pos;
- if (sscanf(optarg, "io,stat,%lf,%n", &interval_float, (int *)&idx)==0) {
- fprintf(stderr, "\ntshark: invalid \"-z io,stat,<interval>[,<filter>]\" argument\n");
+ if ((*(opt_arg+(strlen(opt_arg)-1)) == ',') ||
+ (sscanf(opt_arg, "io,stat,%lf%n", &interval_float, (int *)&idx) != 1) ||
+ (idx < 8)) {
+ fprintf(stderr, "\ntshark: invalid \"-z io,stat,<interval>[,<filter>][,<filter>]...\" argument\n");
exit(1);
}
-
+
+ filters=opt_arg+idx;
+ if (*filters) {
+ if (*filters != ',') {
+ /* For locale's that use ',' instead of '.', the comma might
+ * have been consumed during the floating point conversion. */
+ --filters;
+ if (*filters != ',') {
+ fprintf(stderr, "\ntshark: invalid \"-z io,stat,<interval>[,<filter>][,<filter>]...\" argument\n");
+ exit(1);
+ }
+ }
+ } else
+ filters=NULL;
+
+ switch (timestamp_get_type()) {
+ case TS_DELTA:
+ case TS_DELTA_DIS:
+ case TS_EPOCH:
+ case TS_UTC:
+ case TS_UTC_WITH_DATE:
+ fprintf(stderr, "\ntshark: invalid -t operand. io,stat only supports -t <r|a|ad>\n");
+ exit(1);
+ default:
+ break;
+ }
+
io = (io_stat_t *) g_malloc(sizeof(io_stat_t));
/* If interval is 0, calculate statistics over the whole file by setting the interval to
io->invl_prec = 0;
} else {
/* Set interval to the number of us rounded to the nearest integer */
- io->interval = (gint64)(interval_float*1000000.0+0.5);
+ io->interval = (guint64)(interval_float * 1000000.0 + 0.5);
/*
* Determine what interval precision the user has specified */
io->invl_prec = 6;
- for (i=10; i<10000000; i*=10) {
+ for (i=10; i<10000000; i*=10) {
if (io->interval%i > 0)
break;
io->invl_prec--;
}
+ if (io->invl_prec==0) {
+ /* The precision is zero but if the user specified one of more zeros after the decimal point,
+ they want that many decimal places shown in the table for all time intervals except
+ response time values such as smb.time which always have 6 decimal places of precision.
+ This feature is useful in cases where for example the duration is 9.1, you specify an
+ interval of 1 and the last interval becomes "9 <> 9". If the interval is instead set to
+ 1.1, the last interval becomes
+ last interval is rounded up to value that is greater than the duration. */
+ const gchar *invl_start = opt_arg+8;
+ gchar *intv_end;
+ int invl_len;
+
+ intv_end = g_strstr_len(invl_start, -1, ",");
+ invl_len = (int)(intv_end - invl_start);
+ invl_start = g_strstr_len(invl_start, invl_len, ".");
+
+ if (invl_start != NULL) {
+ invl_len = (int)(intv_end - invl_start - 1);
+ if (invl_len)
+ io->invl_prec = MIN(invl_len, 6);
+ }
+ }
}
if (io->interval < 1){
fprintf(stderr,
io->num_cols = 1;
io->start_time=0;
- if (idx) {
- filters = optarg + idx;
- if (strlen(filters) > 0 ) {
- str = filters;
- while((str = strchr(str, ','))) {
- io->num_cols++;
- str++;
- }
+ if (filters && (*filters != '\0')) {
+ /* Eliminate the first comma. */
+ filters++;
+ str = filters;
+ while((str = strchr(str, ','))) {
+ io->num_cols++;
+ str++;
}
- } else {
- filters=NULL;
}
io->items = (io_stat_item_t *) g_malloc(sizeof(io_stat_item_t) * io->num_cols);
- io->filters = g_malloc(sizeof(char *) * io->num_cols);
+ io->filters = (const char **)g_malloc(sizeof(char *) * io->num_cols);
io->max_vals = (guint64 *) g_malloc(sizeof(guint64) * io->num_cols);
io->max_frame = (guint32 *) g_malloc(sizeof(guint32) * io->num_cols);
for (i=0; i<io->num_cols; i++) {
io->max_vals[i] = 0;
io->max_frame[i] = 0;
- }
+ }
/* Register a tap listener for each filter */
if((!filters) || (filters[0]==0)) {
if(pos==str){
register_io_tap(io, i, NULL);
} else if (pos==NULL) {
- str = (char*) g_strstrip((gchar*)str);
+ str = (const char*) g_strstrip((gchar*)str);
filter = g_strdup((gchar*) str);
if (*filter)
register_io_tap(io, i, filter);
else
register_io_tap(io, i, NULL);
} else {
- filter = g_malloc((pos-str)+1);
+ filter = (gchar *)g_malloc((pos-str)+1);
g_strlcpy( filter, str, (gsize) ((pos-str)+1));
filter = g_strstrip(filter);
register_io_tap(io, i, (char *) filter);
{
register_stat_cmd_arg("io,stat,", iostat_init, NULL);
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=4 expandtab:
+ * :indentSize=4:tabSize=4:noTabs=true:
+ */