Witness: enum witness_notifyResponse_type
[wireshark-wip.git] / ui / cli / tap-comparestat.c
blobeb4ba9f7d33a010a67b96decd72f0bc8956a3da3
1 /* tap-comparestat.c
2 * Compare two capture files
3 * Copyright 2008 Vincenzo Condoleo, Christophe Dirac, Reto Ruoss
4 * supported by HSR (Hochschule Rapperswil)
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 /* This module provides statistics about two merged capture files, to find packet loss,
28 * time delay, ip header checksum errors and order check to tshark.
29 * It's also detecting the matching regions of the different files.
31 * The packets are compared by the ip id. MAC or TTL is used to distinct the different files.
32 * It is only used by tshark and not wireshark
35 #include "config.h"
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
42 #include "epan/packet_info.h"
43 #include <epan/in_cksum.h>
44 #include <epan/packet.h>
45 #include <epan/tap.h>
46 #include <epan/timestamp.h>
47 #include <epan/stat_cmd_args.h>
48 #include <epan/dissectors/packet-ip.h>
49 #include "epan/timestats.h"
52 /* For checksum */
53 #define BYTES 8
54 #define WRONG_CHKSUM 0
56 #define MERGED_FILES 2
58 #define TTL_SEARCH 5
60 void register_tap_listener_comparestat(void);
62 /* information which will be printed */
63 typedef struct _for_print {
64 guint count;
65 guint16 cksum;
66 nstime_t predecessor_time;
67 struct _frame_info *partner;
68 } for_print;
70 /* each tracked packet */
71 typedef struct _frame_info {
72 for_print *fp;
73 guint32 num;
74 guint16 id;
75 guint8 ip_ttl;
76 address dl_dst;
77 nstime_t abs_ts, zebra_time, delta;
78 } frame_info;
80 /* used to keep track of the statistics for an entire program interface */
81 typedef struct _comparestat_t {
82 char *filter;
83 emem_tree_t *packet_tree, *ip_id_tree, *nr_tree;
84 address eth_dst, eth_src;
85 nstime_t zebra_time, current_time;
86 timestat_t stats;
87 GArray *ip_ttl_list;
88 gboolean last_hit;
89 guint32 start_ongoing_hits, stop_ongoing_hits, start_packet_nr_first, start_packet_nr_second, stop_packet_nr_first, stop_packet_nr_second;
90 guint32 first_file_amount, second_file_amount;
91 } comparestat_t;
94 /* to call directly _init */
95 static gdouble compare_variance=0.0;
96 static guint8 compare_start, compare_stop;
97 static gboolean TTL_method=TRUE, ON_method=TRUE;
99 /* This callback is never used by tshark but it is here for completeness. */
100 static void
101 comparestat_reset(void *dummy _U_)
106 /* This callback is invoked whenever the tap system has seen a packet
107 * we might be interested in.
108 * function returns :
109 * 0: no updates, no need to call (*draw) later
110 * !0: state has changed, call (*draw) sometime later
112 static int
113 comparestat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
115 comparestat_t *cs=(comparestat_t *)arg;
116 const ws_ip *ci=(const ws_ip *)arg2;
117 frame_info *fInfo;
118 vec_t cksum_vec[3];
119 guint16 computed_cksum=0;
121 /* so this get filled, usually with the first frame */
122 if(cs->eth_dst.len==0) {
123 cs->eth_dst=pinfo->dl_dst;
124 cs->eth_src=pinfo->dl_src;
127 /* Set up the fields of the pseudo-header and create checksum */
128 cksum_vec[0].ptr=&ci->ip_v_hl;
129 cksum_vec[0].len=BYTES;
130 /* skip TTL */
131 cksum_vec[1].ptr=&ci->ip_p;
132 cksum_vec[1].len=1;
133 /* skip header checksum and ip's (because of NAT)*/
134 cksum_vec[2].ptr=(const guint8 *)ci->ip_dst.data;
135 cksum_vec[2].ptr=cksum_vec[2].ptr+ci->ip_dst.len;
136 /* dynamic computation */
137 cksum_vec[2].len=ci->ip_len-20;
138 computed_cksum=in_cksum(&cksum_vec[0], 3);
140 /* collect all packet infos */
141 fInfo=(frame_info*)se_alloc(sizeof(frame_info));
142 fInfo->fp=(for_print*)se_alloc(sizeof(for_print));
143 fInfo->fp->partner=NULL;
144 fInfo->fp->count=1;
145 fInfo->fp->cksum=computed_cksum;
146 fInfo->num=pinfo->fd->num;
147 fInfo->id=ci->ip_id;
148 fInfo->ip_ttl=ci->ip_ttl;
149 fInfo->dl_dst=pinfo->dl_dst;
150 fInfo->abs_ts=pinfo->fd->abs_ts;
151 /* clean memory */
152 nstime_set_zero(&fInfo->zebra_time);
153 nstime_set_zero(&fInfo->fp->predecessor_time);
154 se_tree_insert32(cs->packet_tree, pinfo->fd->num, fInfo);
156 return 1;
159 /* Find equal packets, same IP-Id, count them and make time statistics */
160 static gboolean
161 call_foreach_count_ip_id(gpointer value, gpointer arg)
163 comparestat_t *cs=(comparestat_t*)arg;
164 frame_info *fInfo=(frame_info*)value, *fInfoTemp;
165 nstime_t delta;
166 guint i;
168 /* we only need one value out of pinfo we use a temp one */
169 packet_info *pinfo=(packet_info*)ep_alloc(sizeof(packet_info));
170 pinfo->fd=(frame_data*)ep_alloc(sizeof(frame_data));
171 pinfo->fd->num = fInfo->num;
173 fInfoTemp=(frame_info *)se_tree_lookup32(cs->ip_id_tree, fInfo->id);
174 if(fInfoTemp==NULL){
175 /* Detect ongoing package loss */
176 if((cs->last_hit==FALSE)&&(cs->start_ongoing_hits>compare_start)&&(cs->stop_ongoing_hits<compare_stop)){
177 cs->stop_ongoing_hits++;
178 cs->stop_packet_nr_first=fInfo->num;
179 } else if(cs->stop_ongoing_hits<compare_stop){
180 cs->stop_ongoing_hits=0;
181 cs->stop_packet_nr_first=G_MAXINT32;
183 cs->last_hit=FALSE;
185 fInfo->fp->count=1;
186 se_tree_insert32(cs->ip_id_tree, fInfo->id, fInfo);
187 } else {
188 /* Detect ongoing package hits, special behavior if start is set to 0 */
189 if((cs->last_hit||(compare_start==0))&&(cs->start_ongoing_hits<compare_start||(compare_start==0))){
190 if((compare_start==0)&&(cs->start_ongoing_hits!=0)){
191 /* start from the first packet so allready set */
192 } else {
193 cs->start_ongoing_hits++;
194 /* Take the lower number */
195 cs->start_packet_nr_first=fInfoTemp->num;
196 cs->start_packet_nr_second=fInfo->num;
198 } else if(cs->start_ongoing_hits<compare_start){
199 cs->start_ongoing_hits=0;
200 cs->start_packet_nr_first=G_MAXINT32;
202 cs->last_hit=TRUE;
204 fInfo->fp->count=fInfoTemp->fp->count + 1;
205 if(fInfoTemp->fp->cksum!=fInfo->fp->cksum){
206 fInfo->fp->cksum=WRONG_CHKSUM;
207 fInfoTemp->fp->cksum=WRONG_CHKSUM;
209 /* Add partner */
210 fInfo->fp->partner=fInfoTemp;
211 /* Create time statistic */
212 if(fInfo->fp->count==MERGED_FILES){
213 nstime_delta(&delta, &fInfo->abs_ts, &fInfoTemp->abs_ts);
214 /* Set delta in both packets */
215 nstime_set_zero(&fInfoTemp->delta);
216 nstime_add(&fInfoTemp->delta, &delta);
217 nstime_set_zero(&fInfo->delta);
218 nstime_add(&fInfo->delta, &delta);
219 time_stat_update(&cs->stats, &delta, pinfo);
221 se_tree_insert32(cs->ip_id_tree, fInfo->id, fInfo);
224 /* collect TTL's */
225 if(TTL_method && (fInfo->num<TTL_SEARCH)){
226 for(i=0; i < cs->ip_ttl_list->len; i++){
227 if(g_array_index(cs->ip_ttl_list, guint8, i) == fInfo->ip_ttl){
228 return FALSE;
231 g_array_append_val(cs->ip_ttl_list, fInfo->ip_ttl);
234 return FALSE;
237 /*Create new numbering */
238 static gboolean
239 call_foreach_new_order(gpointer value, gpointer arg)
241 comparestat_t *cs=(comparestat_t*)arg;
242 frame_info *fInfo=(frame_info*)value, *fInfoTemp;
244 /* overwrite Info column for new ordering */
245 fInfoTemp=(frame_info *)se_tree_lookup32(cs->nr_tree, fInfo->id);
246 if(fInfoTemp==NULL){
247 if(TTL_method==FALSE){
248 if((ADDRESSES_EQUAL(&cs->eth_dst, &fInfo->dl_dst)) || (ADDRESSES_EQUAL(&cs->eth_src, &fInfo->dl_dst))){
249 se_tree_insert32(cs->nr_tree, fInfo->id, fInfo);
250 fInfo->zebra_time=cs->zebra_time;
251 cs->zebra_time.nsecs=cs->zebra_time.nsecs + MERGED_FILES;
252 } else {
253 cs->zebra_time.nsecs++;
254 se_tree_insert32(cs->nr_tree, fInfo->id, fInfo);
255 fInfo->zebra_time=cs->zebra_time;
256 cs->zebra_time.nsecs++;
258 } else {
259 if((g_array_index(cs->ip_ttl_list, guint8, 0)==fInfo->ip_ttl) || (g_array_index(cs->ip_ttl_list, guint8, 1)==fInfo->ip_ttl)){
260 se_tree_insert32(cs->nr_tree, fInfo->id, fInfo);
261 fInfo->zebra_time=cs->zebra_time;
262 cs->zebra_time.nsecs=cs->zebra_time.nsecs + MERGED_FILES;
263 } else {
264 cs->zebra_time.nsecs++;
265 se_tree_insert32(cs->nr_tree, fInfo->id, fInfo);
266 fInfo->zebra_time=cs->zebra_time;
267 cs->zebra_time.nsecs++;
271 } else {
272 if(TTL_method==FALSE){
273 if(((ADDRESSES_EQUAL(&cs->eth_dst, &fInfo->dl_dst)) || (ADDRESSES_EQUAL(&cs->eth_src, &fInfo->dl_dst)))&&(!fmod(fInfoTemp->zebra_time.nsecs,MERGED_FILES))){
274 fInfo->zebra_time.nsecs=fInfoTemp->zebra_time.nsecs;
275 } else {
276 fInfo->zebra_time.nsecs=fInfoTemp->zebra_time.nsecs+1;
278 } else {
279 if(((g_array_index(cs->ip_ttl_list, guint8, 0)==fInfo->ip_ttl) || (g_array_index(cs->ip_ttl_list, guint8, 1)==fInfo->ip_ttl))&&(!fmod(fInfoTemp->zebra_time.nsecs,MERGED_FILES))){
280 fInfo->zebra_time.nsecs=fInfoTemp->zebra_time.nsecs;
281 } else {
282 fInfo->zebra_time.nsecs=fInfoTemp->zebra_time.nsecs+1;
287 /* count packets of file */
288 if(fmod(fInfo->zebra_time.nsecs, MERGED_FILES)){
289 cs->first_file_amount++;
290 } else {
291 cs->second_file_amount++;
294 /* ordering */
295 if(!nstime_is_unset(&cs->current_time)){
296 fInfo->fp->predecessor_time.nsecs=cs->current_time.nsecs;
299 cs->current_time.nsecs=fInfo->zebra_time.nsecs;
301 return FALSE;
304 /* calculate scopes if not set yet */
305 static gboolean
306 call_foreach_merge_settings(gpointer value, gpointer arg)
308 comparestat_t *cs=(comparestat_t*)arg;
309 frame_info *fInfo=(frame_info*)value, *fInfoTemp=NULL;
310 guint32 tot_packet_amount=cs->first_file_amount+cs->second_file_amount, swap;
312 if((fInfo->num==tot_packet_amount)&&(cs->stop_packet_nr_first!=G_MAXINT32)){
313 /* calculate missing stop number */
314 swap=cs->stop_packet_nr_first;
315 cs->stop_packet_nr_first=tot_packet_amount-cs->second_file_amount;
316 cs->stop_packet_nr_second=swap;
319 if((fInfo->num==tot_packet_amount)&&(cs->stop_packet_nr_first==G_MAXINT32)&&(cs->start_packet_nr_first!=G_MAXINT32)){
320 fInfoTemp=(frame_info *)se_tree_lookup32(cs->packet_tree, cs->start_packet_nr_first);
321 if(fInfoTemp==NULL){
322 printf("ERROR: start number not set correctly\n");
323 return FALSE;
325 if(fmod(fInfoTemp->zebra_time.nsecs, 2)){
326 /*first file*/
327 cs->stop_packet_nr_first=cs->start_packet_nr_first+abs(cs->second_file_amount-(cs->start_packet_nr_second-cs->first_file_amount));
328 if(cs->stop_packet_nr_first>(tot_packet_amount-cs->second_file_amount)){
329 cs->stop_packet_nr_first=tot_packet_amount-cs->second_file_amount;
331 /*this only happens if we have too many MAC's or TTL*/
332 if(cs->stop_packet_nr_first>cs->start_packet_nr_second){
333 cs->stop_packet_nr_first=cs->start_packet_nr_second-1;
335 fInfoTemp=(frame_info *)se_tree_lookup32(cs->packet_tree, cs->stop_packet_nr_first);
336 while((fInfoTemp!=NULL)?fmod(!fInfoTemp->zebra_time.nsecs, 2):TRUE){
337 cs->stop_packet_nr_first--;
338 fInfoTemp=(frame_info *)se_tree_lookup32(cs->packet_tree, cs->stop_packet_nr_first);
340 } else {
341 /*this only happens if we have too many MAC's or TTL*/
342 cs->stop_packet_nr_first=cs->first_file_amount+cs->start_packet_nr_first;
343 if(cs->stop_packet_nr_first>tot_packet_amount-cs->first_file_amount){
344 cs->stop_packet_nr_first=tot_packet_amount-cs->first_file_amount;
346 fInfoTemp=(frame_info *)se_tree_lookup32(cs->packet_tree, cs->stop_packet_nr_first);
347 while((fInfoTemp!=NULL)?fmod(fInfoTemp->zebra_time.nsecs, 2):TRUE){
348 cs->stop_packet_nr_first--;
349 fInfoTemp=(frame_info *)se_tree_lookup32(cs->packet_tree, cs->stop_packet_nr_first);
352 /* set second stop location */
353 cs->stop_packet_nr_second=cs->start_packet_nr_second+abs(cs->stop_packet_nr_first-cs->start_packet_nr_first);
354 if(cs->stop_packet_nr_second>tot_packet_amount){
355 cs->stop_packet_nr_second=tot_packet_amount;
359 /* no start found */
360 if(fInfo->num==tot_packet_amount&&compare_start!=0&&compare_stop!=0){
361 if(cs->start_packet_nr_first==G_MAXINT32){
362 printf("Start point couldn't be set, choose a lower compare start");
366 return FALSE;
369 static gboolean
370 call_foreach_print_ip_tree(gpointer value, gpointer user_data)
372 frame_info *fInfo=(frame_info*)value;
373 comparestat_t *cs=(comparestat_t*)user_data;
374 gdouble delta, average;
375 gboolean show_it=FALSE;
377 delta=fabs(get_average(&fInfo->delta,1));
378 average=fabs(get_average(&cs->stats.tot, cs->stats.num));
380 /* special case if both are set to zero ignore start and stop numbering */
381 if(compare_start!=0&&compare_stop!=0){
382 /* check out if packet is in searched scope */
383 if((cs->start_packet_nr_first<fInfo->num)&&(cs->stop_packet_nr_first>fInfo->num)){
384 show_it=TRUE;
385 } else {
386 /* so we won't miss the other file */
387 if((fInfo->num>cs->start_packet_nr_second)&&(fInfo->num<cs->stop_packet_nr_second)){
388 show_it=TRUE;
391 } else {
392 show_it=TRUE;
395 if(show_it){
396 if(fInfo->fp->count < MERGED_FILES){
397 printf("Packet id :%i, count:%i Problem:", fInfo->id, fInfo->fp->count);
398 printf("Packet lost\n");
400 if(fInfo->fp->count > MERGED_FILES){
401 printf("Packet id :%i, count:%i Problem:", fInfo->id, fInfo->fp->count);
402 printf("More than two packets\n");
403 if(fInfo->fp->cksum == WRONG_CHKSUM){
404 printf("Checksum error over IP header\n");
407 if(fInfo->fp->count == MERGED_FILES){
408 if(fInfo->fp->cksum == WRONG_CHKSUM){
409 printf("Packet id :%i, count:%i Problem:", fInfo->id, fInfo->fp->count);
410 printf("Checksum error over IP header\n");
411 if(((delta < (average-cs->stats.variance)) || (delta > (average+cs->stats.variance))) && (delta > 0.0) && (cs->stats.variance!=0)){
412 printf("Not arrived in time\n");
414 if((nstime_cmp(&fInfo->fp->predecessor_time, &fInfo->zebra_time)>0||nstime_cmp(&fInfo->fp->partner->fp->predecessor_time, &fInfo->fp->partner->zebra_time)>0) && (fInfo->zebra_time.nsecs!=MERGED_FILES) && ON_method){
415 printf("Not correct order\n");
417 } else if(((delta < (average-cs->stats.variance)) || (delta > (average+cs->stats.variance))) && (delta > 0.0) && (cs->stats.variance!=0)) {
418 printf("Packet id :%i, count:%i Problem:", fInfo->id, fInfo->fp->count);
419 printf("Package not arrived in time\n");
420 if((nstime_cmp(&fInfo->fp->predecessor_time, &fInfo->zebra_time)>0||nstime_cmp(&fInfo->fp->partner->fp->predecessor_time, &fInfo->fp->partner->zebra_time)>0) && fInfo->zebra_time.nsecs != MERGED_FILES && ON_method){
421 printf("Not correct order\n");
423 } else if((nstime_cmp(&fInfo->fp->predecessor_time, &fInfo->zebra_time)>0||nstime_cmp(&fInfo->fp->partner->fp->predecessor_time, &fInfo->fp->partner->zebra_time)>0) && fInfo->zebra_time.nsecs != MERGED_FILES && ON_method){
424 printf("Packet id :%i, count:%i Problem:", fInfo->id, fInfo->fp->count);
425 printf("Not correct order\n");
429 return FALSE;
433 /* This callback is used when tshark wants us to draw/update our
434 * data to the output device. Since this is tshark only output is
435 * stdout.
436 * TShark will only call this callback once, which is when tshark has
437 * finished reading all packets and exists.
438 * If used with wireshark this may be called any time, perhaps once every 3
439 * seconds or so.
440 * This function may even be called in parallell with (*reset) or (*draw)
441 * so make sure there are no races. The data in the rpcstat_t can thus change
442 * beneath us. Beware.
444 static void
445 comparestat_draw(void *prs)
447 comparestat_t *cs=(comparestat_t *)prs;
448 GString *filter_str = g_string_new("");
449 const gchar *statis_string;
450 guint32 first_file_amount, second_file_amount;
452 /* inital steps, clear all data before start*/
453 cs->zebra_time.secs=0;
454 cs->zebra_time.nsecs=1;
455 nstime_set_unset(&cs->current_time);
456 cs->ip_ttl_list=g_array_new(FALSE, FALSE, sizeof(guint8));
457 cs->last_hit=FALSE;
458 cs->start_ongoing_hits=0;
459 cs->stop_ongoing_hits=0;
460 cs->start_packet_nr_first=G_MAXINT32;
461 cs->start_packet_nr_second=G_MAXINT32;
462 cs->stop_packet_nr_first=G_MAXINT32;
463 cs->stop_packet_nr_second=G_MAXINT32;
464 cs->first_file_amount=0;
465 cs->second_file_amount=0;
467 time_stat_init(&cs->stats);
468 /* not using g_free, because struct is managed by binarytrees */
469 cs->ip_id_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "ip_id_tree");
470 emem_tree_foreach(cs->packet_tree, call_foreach_count_ip_id, cs);
472 /* set up TTL choice if only one number found */
473 if(TTL_method&&cs->ip_ttl_list->len==1){
474 g_array_append_val(cs->ip_ttl_list, g_array_index(cs->ip_ttl_list, guint8, 1));
477 emem_tree_foreach(cs->packet_tree, call_foreach_new_order,cs);
478 emem_tree_foreach(cs->packet_tree, call_foreach_merge_settings, cs);
480 /* remembering file amounts */
481 first_file_amount=cs->first_file_amount;
482 second_file_amount=cs->second_file_amount;
483 /* reset after numbering */
484 cs->nr_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nr_tree");
486 /* Variance */
487 cs->stats.variance=compare_variance;
489 /* add statistic string */
490 statis_string=g_strdup_printf("Compare Statistics: \nFilter: %s\nNumber of packets total:%i 1st file:%i, 2nd file:%i\nScopes:\t start:%i stop:%i\nand:\t start:%i stop:%i\nEqual packets: %i \nAllowed variation: %f \nAverage time difference: %f\n", cs->filter ? cs->filter : "", (first_file_amount+second_file_amount), first_file_amount, second_file_amount, cs->start_packet_nr_first, cs->stop_packet_nr_first, cs->start_packet_nr_second, cs->stop_packet_nr_second, cs->stats.num, cs->stats.variance, fabs(get_average(&cs->stats.tot, cs->stats.num)));
492 printf("\n");
493 printf("===================================================================\n");
494 printf("%s", statis_string);
495 emem_tree_foreach(cs->ip_id_tree, call_foreach_print_ip_tree, cs);
496 printf("===================================================================\n");
497 g_string_free(filter_str, TRUE);
498 g_array_free(cs->ip_ttl_list, TRUE);
501 /* When called, this function will create a new instance of comparestat.
502 * This function is called from tshark when it parses the -z compare, arguments
503 * and it creates a new instance to store statistics in and registers this
504 * new instance for the compare tap.
506 static void
507 comparestat_init(const char *opt_arg, void* userdata _U_)
509 comparestat_t *cs;
510 const char *filter=NULL;
511 GString *error_string;
512 gint start, stop,ttl, order, pos=0;
513 gdouble variance;
515 if(sscanf(opt_arg,"compare,%d,%d,%d,%d,%lf%n",&start, &stop, &ttl, &order, &variance, &pos)==5){
516 if(pos){
517 if(*(opt_arg+pos)==',')
518 filter=opt_arg+pos+1;
519 else
520 filter=opt_arg+pos;
521 } else {
522 filter=NULL;
524 } else {
525 fprintf(stderr, "tshark: invalid \"-z compare,<start>,<stop>,<ttl[0|1]>,<order[0|1]>,<variance>[,<filter>]\" argument\n");
526 exit(1);
529 compare_variance=variance;
530 compare_start=start;
531 compare_stop=stop;
532 TTL_method=ttl;
533 ON_method=order;
535 cs=g_new(comparestat_t,1);
536 nstime_set_unset(&cs->current_time);
537 cs->ip_ttl_list=g_array_new(FALSE, FALSE, sizeof(guint8));
538 cs->last_hit=FALSE;
539 cs->start_ongoing_hits=0;
540 cs->stop_ongoing_hits=0;
541 cs->start_packet_nr_first=G_MAXINT32;
542 cs->start_packet_nr_second=G_MAXINT32;
543 cs->stop_packet_nr_first=G_MAXINT32;
544 cs->stop_packet_nr_second=G_MAXINT32;
545 cs->first_file_amount=0;
546 cs->second_file_amount=0;
548 cs->zebra_time.secs=0;
549 cs->zebra_time.nsecs=1;
550 cs->nr_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nr_tree");
551 /* microsecond precision */
552 timestamp_set_precision(TS_PREC_AUTO_NSEC);
554 if(filter){
555 cs->filter=g_strdup(filter);
556 } else {
557 cs->filter=NULL;
560 /* create a Hash to count the packets with the same ip.id */
561 cs->packet_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "Packet_info_tree");
563 error_string=register_tap_listener("ip", cs, filter, 0, comparestat_reset, comparestat_packet, comparestat_draw);
564 if(error_string){
565 /* error, we failed to attach to the tap. clean up */
566 g_free(cs->filter);
567 g_free(cs);
569 fprintf(stderr, "tshark: Couldn't register compare tap: %s\n", error_string->str);
570 g_string_free(error_string, TRUE);
571 exit(1);
576 void
577 register_tap_listener_comparestat(void)
579 register_stat_cmd_arg("compare,", comparestat_init,NULL);