2 * Compare two capture files
3 * Copyright 2008 Vincenzo Condoleo, Christophe Dirac, Reto Ruoss
4 * supported by HSR (Hochschule Rapperswil)
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
42 #include "epan/packet_info.h"
43 #include <epan/in_cksum.h>
44 #include <epan/packet.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"
54 #define WRONG_CHKSUM 0
56 #define MERGED_FILES 2
60 void register_tap_listener_comparestat(void);
62 /* information which will be printed */
63 typedef struct _for_print
{
66 nstime_t predecessor_time
;
67 struct _frame_info
*partner
;
70 /* each tracked packet */
71 typedef struct _frame_info
{
77 nstime_t abs_ts
, zebra_time
, delta
;
80 /* used to keep track of the statistics for an entire program interface */
81 typedef struct _comparestat_t
{
83 emem_tree_t
*packet_tree
, *ip_id_tree
, *nr_tree
;
84 address eth_dst
, eth_src
;
85 nstime_t zebra_time
, current_time
;
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
;
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. */
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.
109 * 0: no updates, no need to call (*draw) later
110 * !0: state has changed, call (*draw) sometime later
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
;
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
;
131 cksum_vec
[1].ptr
=&ci
->ip_p
;
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
;
145 fInfo
->fp
->cksum
=computed_cksum
;
146 fInfo
->num
=pinfo
->fd
->num
;
148 fInfo
->ip_ttl
=ci
->ip_ttl
;
149 fInfo
->dl_dst
=pinfo
->dl_dst
;
150 fInfo
->abs_ts
=pinfo
->fd
->abs_ts
;
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
);
159 /* Find equal packets, same IP-Id, count them and make time statistics */
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
;
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
);
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
;
186 se_tree_insert32(cs
->ip_id_tree
, fInfo
->id
, fInfo
);
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 */
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
;
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
;
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
);
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
){
231 g_array_append_val(cs
->ip_ttl_list
, fInfo
->ip_ttl
);
237 /*Create new numbering */
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
);
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
;
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
++;
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
;
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
++;
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
;
276 fInfo
->zebra_time
.nsecs
=fInfoTemp
->zebra_time
.nsecs
+1;
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
;
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
++;
291 cs
->second_file_amount
++;
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
;
304 /* calculate scopes if not set yet */
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
);
322 printf("ERROR: start number not set correctly\n");
325 if(fmod(fInfoTemp
->zebra_time
.nsecs
, 2)){
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
);
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
;
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");
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
)){
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
)){
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");
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
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
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.
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
));
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");
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
)));
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.
507 comparestat_init(const char *opt_arg
, void* userdata _U_
)
510 const char *filter
=NULL
;
511 GString
*error_string
;
512 gint start
, stop
,ttl
, order
, pos
=0;
515 if(sscanf(opt_arg
,"compare,%d,%d,%d,%d,%lf%n",&start
, &stop
, &ttl
, &order
, &variance
, &pos
)==5){
517 if(*(opt_arg
+pos
)==',')
518 filter
=opt_arg
+pos
+1;
525 fprintf(stderr
, "tshark: invalid \"-z compare,<start>,<stop>,<ttl[0|1]>,<order[0|1]>,<variance>[,<filter>]\" argument\n");
529 compare_variance
=variance
;
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
));
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
);
555 cs
->filter
=g_strdup(filter
);
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
);
565 /* error, we failed to attach to the tap. clean up */
569 fprintf(stderr
, "tshark: Couldn't register compare tap: %s\n", error_string
->str
);
570 g_string_free(error_string
, TRUE
);
577 register_tap_listener_comparestat(void)
579 register_stat_cmd_arg("compare,", comparestat_init
,NULL
);