2 * iostat 2002 Ronnie Sahlberg
4 * $Id: tap-iostat.c,v 1.4 2003/04/22 09:02:47 sahlberg Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
36 #include "epan/packet_info.h"
41 typedef struct _io_stat_t {
42 gint32 interval; /* unit is ms */
44 struct _io_stat_item_t *items;
48 typedef struct _io_stat_item_t {
50 struct _io_stat_item_t *next;
51 struct _io_stat_item_t *prev;
52 gint32 time; /* unit is ms since start of capture */
58 /* Tethereal does not use the reset callback.
59 But if someone ports this feature to Gtk with a nice gui, this is what
60 reset should look like.
63 iostat_reset(io_stat_item_t *mit)
78 /* function to remove and clean up an io stat. would be used by Gtk/Gtk2 version
79 io iostat when the iostat window is closed.
82 iostat_cleanup(io_stat_t *io)
86 for(i=0;i<io->num_items;i++){
91 iostat_reset(&io->items[i]);
92 remove_tap_listener(&io->items[i]);
102 iostat_packet(io_stat_item_t *mit, packet_info *pinfo, epan_dissect_t *edt _U_, void *dummy _U_)
107 current_time=((pinfo->fd->rel_secs*1000)+(pinfo->fd->rel_usecs/1000));
109 /* the prev item before the main one is always the last interval we saw packets for */
112 /* XXX for the time being, just ignore all frames that are in the past.
113 should be fixed in the future but hopefully it is uncommon */
114 if(current_time<it->time){
118 /* we have moved into a new interval, we need to create a new struct */
119 if(current_time>=(it->time+mit->parent->interval)){
120 it->next=g_malloc(sizeof(io_stat_item_t));
126 it->time=(current_time / mit->parent->interval) * mit->parent->interval;
131 /* it will now give us the current structure to use to store the data in */
133 it->bytes+=pinfo->fd->pkt_len;
139 iostat_draw(io_stat_item_t *mit)
142 io_stat_item_t **items;
145 guint32 i,more_items;
151 printf("===================================================================\n");
152 printf("IO Statistics\n");
153 printf("Interval: %d secs\n", iot->interval);
154 for(i=0;i<iot->num_items;i++){
155 printf("Column #%d: %s\n",i,iot->filters[i]?iot->filters[i]:"");
158 for(i=0;i<iot->num_items;i++){
159 printf("| Column #%-2d ",i);
163 for(i=0;i<iot->num_items;i++){
164 printf("|frames| bytes ");
168 items=g_malloc(sizeof(io_stat_item_t *)*iot->num_items);
169 frames=g_malloc(sizeof(guint32)*iot->num_items);
170 bytes=g_malloc(sizeof(guint32)*iot->num_items);
171 /* preset all items at the first interval */
172 for(i=0;i<iot->num_items;i++){
173 items[i]=&iot->items[i];
176 /* loop the items until we run out of them all */
180 for(i=0;i<iot->num_items;i++){
184 for(i=0;i<iot->num_items;i++){
185 if(items[i] && (t>=(items[i]->time+iot->interval))){
186 items[i]=items[i]->next;
189 if(items[i] && (t<(items[i]->time+iot->interval)) && (t>=items[i]->time) ){
190 frames[i]=items[i]->frames;
191 bytes[i]=items[i]->bytes;
200 printf("%03d.%03d-%03d.%03d ",
202 (t+iot->interval)/1000,(t+iot->interval)%1000);
203 for(i=0;i<iot->num_items;i++){
204 printf("%6d %9d ",frames[i],bytes[i]);
212 printf("===================================================================\n");
221 register_io_tap(io_stat_t *io, int i, char *filter)
223 io->items[i].prev=&io->items[i];
224 io->items[i].next=NULL;
225 io->items[i].parent=io;
227 io->items[i].frames=0;
228 io->items[i].bytes=0;
229 io->filters[i]=filter;
231 if(register_tap_listener("frame", &io->items[i], filter, NULL, (void*)iostat_packet, i?NULL:(void*)iostat_draw)){
234 fprintf(stderr,"tethereal: iostat_init() failed to attach tap\n");
240 iostat_init(char *optarg)
242 float interval_float;
248 if(sscanf(optarg,"io,stat,%f,%n",&interval_float,&pos)==1){
255 fprintf(stderr, "tethereal: invalid \"-z io,stat,<interval>[,<filter>]\" argument\n");
260 /* make interval be number of ms */
261 interval=interval_float*1000;
263 fprintf(stderr, "tethereal:iostat_init() interval must be >=0.001 seconds\n");
267 io=g_malloc(sizeof(io_stat_t));
268 io->interval=interval;
269 if((!filter)||(filter[0]==0)){
271 io->items=g_malloc(sizeof(io_stat_item_t)*io->num_items);
272 io->filters=g_malloc(sizeof(char *)*io->num_items);
274 register_io_tap(io, 0, NULL);
278 /* find how many ',' separated filters we have */
281 while((str=strchr(str,','))){
286 io->items=g_malloc(sizeof(io_stat_item_t)*io->num_items);
287 io->filters=g_malloc(sizeof(char *)*io->num_items);
289 /* for each filter, register a tap listener */
295 register_io_tap(io, i, NULL);
296 } else if(pos==NULL) {
297 tmp=g_malloc(strlen(str)+1);
299 register_io_tap(io, i, tmp);
301 tmp=g_malloc((pos-str)+1);
302 strncpy(tmp,str,(pos-str));
304 register_io_tap(io, i, tmp);
313 register_tap_listener_iostat(void)
315 register_ethereal_tap("io,stat,", iostat_init, NULL, NULL);