diff -Naur tcptrace-6.6.7/avl.c tcptrace-6.6.7_4.ftw/avl.c --- tcptrace-6.6.7/avl.c 2004-11-04 22:44:53.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/avl.c 2005-02-10 11:02:21.000000000 +0100 @@ -409,6 +409,7 @@ target->ptp = (*n)->ptp; tmp = *n; (*n) = (*n)->left; + FreePtpSnap(tmp); return 1; } @@ -449,6 +450,7 @@ target->ptp = (*n)->ptp; tmp = *n; *n = (*n)->right; + FreePtpSnap(tmp); return 1; } @@ -504,7 +506,8 @@ return tmp; } } - + + FreePtpSnap(*root); *root = NULL; return BALANCE; } diff -Naur tcptrace-6.6.7/Makefile.in tcptrace-6.6.7_4.ftw/Makefile.in --- tcptrace-6.6.7/Makefile.in 2004-03-04 21:33:56.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/Makefile.in 2004-12-02 11:14:06.000000000 +0100 @@ -21,7 +21,7 @@ # - we'll do path search on the string you specify. If the program # isn't in your path, you'll need to give the absolute path name. # - if you want other formats, see the "compress.h" file. - +DEFINES += -D_BSD_SOURCE ################################################################## diff -Naur tcptrace-6.6.7/output.c tcptrace-6.6.7_4.ftw/output.c --- tcptrace-6.6.7/output.c 2003-11-19 15:38:04.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/output.c 2005-03-22 17:04:59.000000000 +0100 @@ -229,10 +229,17 @@ * has been requested. */ if(csv || tsv || (sv != NULL)) { + /* BEGIN:FV fprintf(stdout,"%s%s%s%s%s%s%s%s", ptp->a_hostname, sp, ptp->b_hostname, sp, ptp->a_portname, sp, ptp->b_portname, sp); - sv_print_count += 4; +*/ + fprintf(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s", + host1,sp,host2, sp, + ptp->a_hostname, sp, ptp->b_hostname, sp, + ptp->a_portname, sp, ptp->b_portname, sp); + /*END:FV*/ + sv_print_count += 6; /* Print the start and end times. In other words, * print the time of the first and the last packet */ @@ -585,6 +592,24 @@ Stdev(pba->retr_tm_sum, pba->retr_tm_sum2, pba->retr_tm_count) / 1000.0); } + + if (print_timeout){ + StatLineI("spurious rto:","", + pab->stat_spurious_rto,pba->stat_spurious_rto); + StatLineI("normal rto:","", + pab->stat_normal_rto,pba->stat_normal_rto); + StatLineI("fast rexmit:","", + pab->stat_fast_rexmit,pba->stat_fast_rexmit); + StatLineI("ambiguos rto:","", + pab->stat_ambiguos_rto,pba->stat_ambiguos_rto); + StatLineI("rtx during srto:","", + pab->stat_rtx_during_srto,pba->stat_rtx_during_srto); + StatLineI("rtx during nrto:","", + pab->stat_rtx_during_nrto,pba->stat_rtx_during_nrto); + StatLineI("rtx during frtx:","", + pab->stat_rtx_during_frtx,pba->stat_rtx_during_frtx); + + } if(csv || tsv || (sv != NULL)) { printf("\n"); @@ -980,6 +1005,7 @@ char *svHeader1[] = { "conn_#" , + "letter_a" , "letter_b", "host_a" , "host_b", "port_a" , "port_b", "first_packet" , "last_packet", @@ -1059,7 +1085,7 @@ "RTT_full_sz_min_a2b" , "RTT_full_sz_min_b2a", "RTT_full_sz_max_a2b" , "RTT_full_sz_max_b2a", "RTT_full_sz_avg_a2b" , "RTT_full_sz_avg_b2a", - "RTT full_sz_stdev_a2b" , "RTT_full_sz_stdev_b2a", + "RTT_full_sz_stdev_a2b" , "RTT_full_sz_stdev_b2a", "post-loss_acks_a2b" , "post-loss_acks_b2a", "ambiguous_acks_a2b" , "ambiguous_acks_b2a", "RTT_min_(last)_a2b" , "RTT_min_(last)_b2a", @@ -1077,6 +1103,21 @@ }; #define SV_RTT_HEADER_COLUMN_COUNT (sizeof(svRTTHeader)/sizeof(char*)) + /* BEGIN:FV */ + + char *svTimeoutHeader[] = { + "spurious_rto_a2b" , "spurious_rto_b2a", + "normal_rto_a2b" , "normal_rto_b2a", + "fast_rexmit_a2b" , "fast_rexmit_b2a", + "ambiguos_rto_a2b" , "ambiguos_rto_b2a", + "rtx_during_srto_a2b" , "rtx_during_srto_b2a", + "rtx_during_nrto_a2b" , "rtx_during_nrto_b2a", + "rtx_during_frtx_a2b" , "rtx_during_frtx_b2a" + }; + + # define SV_TIMEOUT_HEADER_COLUMN_COUNT (sizeof(svTimeoutHeader)/sizeof(char*)) + /* END:FV*/ + /* Local Variables */ u_int i = 0; /* Counter */ @@ -1127,6 +1168,14 @@ for(i = 0; i < SV_RTT_HEADER_COLUMN_COUNT; i++) fprintf(stdout, "%s%s", svRTTHeader[i], sp); + /* BEGIN:FV */ + + if (print_timeout) + for (i=0;i3) { fprintf(stderr,"SV_HEADER_COUNT : -l alone = %d\n", \ diff -Naur tcptrace-6.6.7/pool.c tcptrace-6.6.7_4.ftw/pool.c --- tcptrace-6.6.7/pool.c 2003-11-19 15:38:04.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/pool.c 2005-02-10 12:40:31.000000000 +0100 @@ -69,18 +69,7 @@ #ifndef _BASIC_POOL_H #define _BASIC_POOL_H - -struct Block { - struct Block *next; -}; - -struct Pool { - unsigned int block_size; /* size of a memory block */ - unsigned int block_no; /* number of block in the pool */ - struct Block *list; /* pointer to a list of free blocks */ - short sorted; /* whether list of blocks should be sorted */ -}; - + #define DFLT_POOLS_NUM 10 /* default number of pools */ #define DFLT_BLOCKS_NUM 16 /* default number of blocks in free list */ @@ -88,7 +77,7 @@ * size for each memory pool */ /* global variables */ -static struct Pool *pools = NULL; /* table of memory pools */ +struct Pool *pools = NULL; /* table of memory pools */ static unsigned table_size = 0; /* size of the pool table */ static int pool_num = 0; /* number of existing memory pools */ @@ -187,7 +176,7 @@ unsigned bnumber; if (0) { - printf("PoolMalloc(%0x, %0x) called.. ", poolid, bytes); + fprintf(stderr,"PoolMalloc(%0x, %0x) called.. ", poolid, bytes); } if ((poolid >= pool_num) || (poolid < 0)) { @@ -292,9 +281,6 @@ void *buffer = NULL; unsigned buffer_size = 0; - if (0) { - printf("PoolValloc(%0x, %0x) called\n", poolid, bnumber); - } /* find out how many memory pages we need and allocate such amount * of memory @@ -332,6 +318,9 @@ pools[poolid].block_no += floor(buffer_size/(float)pools[poolid].block_size); (*bsize) = buffer_size; + if (0) { + fprintf(stderr,"PoolValloc(%0x, %0x) %d called\n", poolid, bnumber,pools[poolid].block_no); + } return buffer; } @@ -499,6 +488,7 @@ /* linked list for that pool id is empty */ if (pools[poolid].list == NULL) { block->next = NULL; + pools[poolid].block_no++; /*BEGIN:FV Line Added*/ pools[poolid].list = block; return; } @@ -529,5 +519,4 @@ pools[poolid].block_no++; } - #endif diff -Naur tcptrace-6.6.7/pool.h tcptrace-6.6.7_4.ftw/pool.h --- tcptrace-6.6.7/pool.h 2003-11-19 15:38:08.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/pool.h 2005-02-10 12:15:53.000000000 +0100 @@ -53,6 +53,19 @@ */ #ifndef _POOL_H #define _POOL_H + + +struct Block { + struct Block *next; +}; + +struct Pool { + unsigned int block_size; /* size of a memory block */ + unsigned int block_no; /* number of block in the pool */ + struct Block *list; /* pointer to a list of free blocks */ + short sorted; /* whether list of blocks should be sorted */ +}; + static char const GCC_UNUSED rcsid_pool[] = "@(#)$Header: /usr/local/cvs/tcptrace/pool.h,v 5.4 2003/11/19 14:38:08 sdo Exp $"; diff -Naur tcptrace-6.6.7/rexmit.c tcptrace-6.6.7_4.ftw/rexmit.c --- tcptrace-6.6.7/rexmit.c 2003-11-19 15:38:05.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/rexmit.c 2005-04-21 12:47:08.000000000 +0200 @@ -104,10 +104,20 @@ segment *); static enum t_ack rtt_ackin (tcb *, segment *, - Bool rexmit); + Bool rexmit, + unsigned); static void dump_rtt_sample (tcb *, segment *, double); + +/*BEGIN:FV*/ +static void dump_rtt_sample_global (tcb*, + segment *, + double, + unsigned, + unsigned); +/*END:FV*/ + static void graph_rtt_sample (tcb *, segment *, unsigned long); @@ -423,7 +433,8 @@ static enum t_ack rtt_ackin (tcb * ptcb, segment * pseg, - Bool rexmit_prev) + Bool rexmit_prev, + unsigned tcp_data_length) { double etime_rtt; enum t_ack ret; @@ -516,6 +527,16 @@ dump_rtt_sample (ptcb, pseg, etime_rtt); } + /* BEGIN:FV */ + + /* dump RTT samples in a single file, if asked */ + if (dump_rtt_global && (etime_rtt != 0.0)) { + dump_rtt_sample_global (ptcb, pseg, etime_rtt, + current_size, tcp_data_length); + } + + /* END:FV */ + /* plot RTT samples, if asked */ if (graph_rtt && (pseg->retrans == 0)) { graph_rtt_sample (ptcb, pseg, etime_rtt); @@ -667,8 +688,9 @@ /* if ANY preceding segment was xmitted after this one, the the RTT sample is invalid */ intervening_xmits = (tv_gt (last_xmit, pseg->time)); - - ret = rtt_ackin (ptcb, pseg, intervening_xmits); + /*BEGIN:FV*/ + ret = rtt_ackin (ptcb, pseg, intervening_xmits,tcp_data_length); + /*END:FV*/ } else { /* cumulatively ACKed */ ++ptcb->rtt_cumack; @@ -736,6 +758,44 @@ (int) (etime_rtt / 1000) /* convert from us to ms */ ); } +/* BEGIN:FV */ +/* dump RTT samples in milliseconds in a single file*/ +static void +dump_rtt_sample_global (tcb * ptcb, + segment * pseg, + double etime_rtt, + unsigned current_size, + unsigned tcp_data_length) +{ + if (rtt_dump_file_global == NULL) { + /* try to open the file */ + if ((rtt_dump_file_global = Mfopen(rtt_output_filename, "w")) == NULL) { + perror(rtt_output_filename); + exit(-1); + } + Mfprintf (rtt_dump_file_global, + "#time hosta hostb rtt datasize acksize\n"); + } + if (ptcb == &ptcb->ptp->a2b) { + Mfprintf (rtt_dump_file_global, "%lu.%lu %lu %s\t %s %lu %lu %lu\n", + current_time.tv_sec, current_time.tv_usec, + ptcb->ptp->connection_number+1, + ptcb->ptp->a_hostname,ptcb->ptp->b_hostname, + (int) (etime_rtt / 1000), current_size, + tcp_data_length + /* convert from us to ms */ ); + }else{ + Mfprintf (rtt_dump_file_global, "%lu.%lu %lu %s\t %s %lu %lu %lu\n", + current_time.tv_sec, current_time.tv_usec, + ptcb->ptp->connection_number+1, + ptcb->ptp->b_hostname,ptcb->ptp->a_hostname, + (int) (etime_rtt / 1000), current_size, + tcp_data_length + /* convert from us to ms */ ); + } +} + +/* END:FV */ /* graph RTT samples in milliseconds */ @@ -789,3 +849,77 @@ return TRUE; } + + +/*BEGIN:FV New Function to check if the RTO is spurious; it returns +0 if it is a Fast Retransmit +1 if it is a Necessary RTO +2 if it is Spurious +3 if it is Spurious with SACK +*/ + +int IsSRTO(tcb *ptcb, seqnum s, int segtime) { + quadrant *pquad = whichquad(ptcb->ss,s); + segment *pseg; + int retu = 0; + for (pseg = pquad->seglist_head; pseg != NULL; pseg = pseg->next) { + /*I'm looing for the next segment */ + if (s == (pseg->seq_lastbyte+1)) { + if (pseg->acked == 1) { + /* maybe spurious RTO */ + //fprintf(stdout,"rexmit.c: maybe spurious RTO seqno %lu acked %d times, at %d\n",(u_long)s,pseg->acked, segtime); + retu = 2; + } + + if (pseg->acked == 0) { + /* maybe spurious RTO */ + //fprintf(stdout,"rexmit.c: maybe spurious RTO (not spurious with SACK) seqno %lu acked %d times, at %d\n",(u_long)s,pseg->acked, segtime); + retu = -1; + } + /*THE LAST CASE IS NEEDED TO AVOID WRONG COUNTING OF SPURIOUS IN SOME + CASES... IT IS OK??? IN CASE OF SACK WHAT HAPPEN?*/ + + + + if ((pseg->acked > 1)&&(pseg->acked < 4)) { + /* normal RTO */ + //fprintf(stdout,"rexmit.c: normal RTO seqno %lu acked %d times at %d\n",(u_long)s,pseg->acked,segtime); + retu = 1; + } + //if (retu==0) fprintf(stdout, "rexmit.c: fast retransmit seqno %lu at %d\n", (u_long)s,segtime); + return retu; + } + } + //fprintf(stdout, "rexmit.c: normal RTO (???) seqno %lu at %d\n", (u_long)s,segtime); + return 1; +} + + +/*Is out of order function, return: + +0 if ambiguos +1 if outoforder +2 if fastrexmit + +The function assume that if no ack has been received for that it is out of order +*/ + +int IsOOO(tcb *ptcb, seqnum s) { + quadrant *pquad = whichquad(ptcb->ss,s); + segment *pseg; + + for (pseg = pquad->seglist_head; pseg != NULL; pseg = pseg->next) { + if (s == (pseg->seq_lastbyte+1)) { + if (pseg->acked == 0) return 1; + if (pseg->acked >= 4) return 2; + return FALSE; + } + } + + return TRUE; +} +/*END:FV*/ + + + + diff -Naur tcptrace-6.6.7/tcptrace.c tcptrace-6.6.7_4.ftw/tcptrace.c --- tcptrace-6.6.7/tcptrace.c 2004-10-01 23:42:34.000000000 +0200 +++ tcptrace-6.6.7_4.ftw/tcptrace.c 2005-04-21 12:45:17.000000000 +0200 @@ -62,8 +62,8 @@ #include "modules.h" #include "version.h" - -/* version information */ + + /* version information */ char *tcptrace_version = VERSION; @@ -100,6 +100,11 @@ /* option flags and default values */ Bool colorplot = TRUE; Bool dump_rtt = FALSE; +/*BEGIN:FV*/ +Bool dump_rtt_global = FALSE; +Bool print_timeout = FALSE; +Bool print_timeout_dump=FALSE; +/*END:FV*/ Bool graph_rtt = FALSE; Bool graph_tput = FALSE; Bool graph_tsg = FALSE; @@ -179,6 +184,13 @@ char *cur_filename; static char *progname; char *output_filename = NULL; + +/*BEGIN:FV*/ +static MFILE *rtt_dump_file_global = NULL; +static u_int timeout=TIMEOUT_INTERVAL; +char *rtt_output_filename = NULL; +/*END:FV*/ + static char *update_interval_st = NULL; static char *max_conn_num_st = NULL; static char *live_conn_interval_st = NULL; @@ -568,6 +580,9 @@ -b brief output format\n\ -l long output format\n\ -r print rtt statistics (slower for large files)\n\ + -Q print timeout statistics\n\ + -Qd and dump RTO sample to stdout\n\ + -U dump rtt samples in rtt_samples file\n\ -W report on estimated congestion window (not generally useful)\n\ -q no output (if you just want modules output)\n\ Graphing options\n\ @@ -854,7 +869,7 @@ u_long fpnum = 0; Bool is_stdin = 0; static int file_count = 0; - + /* share the current file name */ cur_filename = filename; @@ -1193,6 +1208,60 @@ /* signal can happen EXACTLY HERE, when data structures are consistant */ sigprocmask(SIG_BLOCK, &mask, NULL); } + + + /*BEGIN:FV dump tcp connection closed and remove for memory save*/ + if (!run_continuously){ + if (elapsed(first_packet,current_time)/1000000>timeout){ + int connSTART,block0START,block1START,block2START; + if (1) { + fprintf(stderr,"START activeconn: %lu tcpconn: %lu TIME %lu min.\n",num_active_tcp_pairs,num_tcp_pairs,timeout/60); + fprintf(stderr,"ptp_snap_block %d\n",pools[0].block_no); + fprintf(stderr,"tcp_pair_block %d\n",pools[1].block_no); + fprintf(stderr,"seqspace_block %d\n",pools[2].block_no); + connSTART=num_active_tcp_pairs; + block0START=pools[0].block_no; + block1START=pools[1].block_no; + block2START=pools[2].block_no; + } + int ix; + int dumped_1=0; + int dumped_2=0; + for (ix = 0; ix <= num_active_tcp_pairs; ++ix) { + if (dumped_pairs[ix]==FALSE){ + if ((FinCount(ttp[ix])>=2)&& + (ttp[ix]->closed_conn>1)&& + (elapsed(ttp[ix]->a2b.last_time,current_time)/1000000>120)&& + (elapsed(ttp[ix]->b2a.last_time,current_time)/1000000>120) + /*I wait for 120 second before dump a closed connection*/){ + DumpConnection(ttp[ix]); + dumped_1++; + } + else if ((elapsed(ttp[ix]->a2b.last_time,current_time)/1000000>CONNECTION_TIMEOUT) + &&(elapsed(ttp[ix]->b2a.last_time,current_time)/1000000>CONNECTION_TIMEOUT)){ + DumpConnection(ttp[ix]); + dumped_2++; + } + } + } + if (1) { + fprintf(stderr,"END activeconn: %lu tcpconn: %lu \n",num_active_tcp_pairs,num_tcp_pairs); + fprintf(stderr,"ptp_snap_block %d\n",pools[0].block_no); + fprintf(stderr,"tcp_pair_block %d\n",pools[1].block_no); + fprintf(stderr,"seqspace_block %d\n",pools[2].block_no); + fprintf(stderr,"Dumped %d Connections Closed and %d Timeouted\n",dumped_1,dumped_2); + if ((connSTART-num_active_tcp_pairs==pools[0].block_no-block0START)&& + (2*(connSTART-num_active_tcp_pairs)==(pools[2].block_no-block2START))&& + (connSTART-num_active_tcp_pairs==pools[1].block_no-block1START)) + fprintf(stderr,"ALL MEMORY DEALLOCATED\n"); + else fprintf(stderr,"NO ALL MEMORY DELLOCATED\n"); + } + + timeout+=TIMEOUT_INTERVAL; + + } + } + /*END:FV*/ } /* set ^C back to the default */ @@ -2154,6 +2223,22 @@ case 'W': print_owin = TRUE; break; case 'X': hex = TRUE; break; case 'Z': dump_rtt = TRUE; break; + /*BEGIN:FV*/ + case 'U': + if (*(argv[i]+1)) { + /*-Ufile*/ + rtt_output_filename = strdup(argv[i]+1); + *(argv[i]+1) = '\00'; + dump_rtt_global = TRUE;break; + } else { + BadArg(argsource, "-Ufile requires a file name for rtt samples\n"); + } + case 'Q': + print_timeout = TRUE; + if (strcmp(argv[i],"Qd") == 0) + print_timeout_dump = TRUE; + break; + /*END:FV*/ case 'b': printbrief = TRUE; break; case 'c': ignore_non_comp = TRUE; break; case 'd': ++debug; break; @@ -2270,6 +2355,16 @@ case 'W': print_owin = !TRUE; break; case 'X': hex = !TRUE; break; case 'Z': dump_rtt = !TRUE; break; + /*BEGIN:FV*/ + case 'U': dump_rtt_global = !TRUE; + printf("I shouldnt be here"); + break; + case 'Q': + print_timeout = !TRUE; + if (strcmp(argv[i],"Qd") == 0) + print_timeout_dump = !TRUE; + break; + /*END:FV*/ case 'b': printbrief = !TRUE; break; case 'c': ignore_non_comp = !TRUE; break; case 'e': save_tcp_data = FALSE; break; diff -Naur tcptrace-6.6.7/tcptrace.h tcptrace-6.6.7_4.ftw/tcptrace.h --- tcptrace-6.6.7/tcptrace.h 2004-11-04 22:55:38.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/tcptrace.h 2005-04-21 12:44:01.000000000 +0200 @@ -69,7 +69,6 @@ static char const GCC_UNUSED rcsid_tcptrace[] = "@(#)$Header: /usr/local/cvs/tcptrace/tcptrace.h,v 5.78 2004/11/04 21:55:38 sdo Exp $"; - #include #include #include @@ -104,8 +103,8 @@ #include "ipv6.h" /* dynamic string support */ -#include "dstring.h" +#include "dstring.h" /* memory allocation routines */ #include "pool.h" @@ -263,6 +262,17 @@ extern u_long tcp_trace_count; extern u_long udp_trace_count; + +#ifdef OLD +/* test 2 IP addresses for equality */ +#define IP_SAMEADDR(addr1,addr2) (((addr1).s_addr) == ((addr2).s_addr)) +/* test for an IP address lower than the second IP address */ +#define IP_LOWADDR(addr1,addr2) (((addr1).s_addr) < ((addr2).s_addr)) + +/* copy IP addresses */ +#define IP_COPYADDR(toaddr,fromaddr) ((toaddr).s_addr = (fromaddr).s_addr) +#endif + typedef struct segment { seqnum seq_firstbyte; /* seqnumber of first byte */ seqnum seq_lastbyte; /* seqnumber of last byte */ @@ -356,7 +366,8 @@ u_int seq_wrap_count; /* wrap count */ /* hardware duplicate detection */ -#define SEGS_TO_REMEMBER 8 +//#define SEGS_TO_REMEMBER 8 +#define SEGS_TO_REMEMBER 4 struct str_hardware_dups { seqnum hwdup_seq; /* sequence number */ u_short hwdup_id; /* IP ID */ @@ -495,6 +506,38 @@ u_long recovered, recovered_orig, rto_segment, lastackno; u_long event_retrans, event_dupacks; + /*BEGIN:FV*/ + /* change Thomas Ziegler to detect spurious RTOs*/ + + + + Bool in_srto,in_nrto,in_frtx; + u_long srto_segment, + srto_segment_end, + srecovered, + srecovered_orig; + u_long nrto_segment, + nrto_segment_end, + nrecovered, + nrecovered_orig; + u_long frecovered, + frecovered_orig; + u_short rtx_during_srto, + rtx_during_nrto, + rtx_during_frtx; + + /*Statistics*/ + u_short stat_spurious_rto; + u_short stat_normal_rto; + u_short stat_fast_rexmit; + u_short stat_rtx_during_nrto; + u_short stat_rtx_during_srto; + u_short stat_rtx_during_frtx; + u_short stat_ambiguos_rto; + + + /*END:FV*/ + /* host name letter(s) */ char *host_letter; } tcb; @@ -514,7 +557,15 @@ struct stcp_pair { /* are we ignoring this one?? */ Bool ignore_pair; - + /*BEGIN:FV + * closed_conn indicated the number of packet received after 2 FYN + * ttp_number is the ttp array index of the tcp_pair + * */ + u_int closed_conn; + int ttp_number; + u_long connection_number; + /*END:FV*/ + /* inactive (previous instance of current connection */ Bool inactive; @@ -547,9 +598,11 @@ typedef struct tcphdr tcphdr; - -extern int num_tcp_pairs; /* how many pairs are in use */ +extern struct Pool * pools; +extern int num_tcp_pairs; /*BEGIN:FV how many pairs have been seen */ +extern int num_active_tcp_pairs; /*BEGIN:FV how many pairs active*/ extern tcp_pair **ttp; /* array of pointers to allocated pairs */ +extern Bool *dumped_pairs; /* BEGIN:FV array of Bool for the deallocated pairs */ /* Wed Aug 20, 2003 - Ramani*/ /* Prior to version 6.4.11, the data structure for storing the snapshots of @@ -608,11 +661,20 @@ tcp_pair *ptp; } ptp_ptr; -#define NONREAL_LIVE_CONN_INTERVAL 4*60 /* 4 minutes */ -#define REMOVE_LIVE_CONN_INTERVAL 8*3600 /* 8 hours */ -#define REMOVE_CLOSED_CONN_INTERVAL 8*60 /* 8 minutes */ -#define UPDATE_INTERVAL 30 /* 30 seconds */ -#define MAX_CONN_NUM 50000 /* max number of connections */ +#define NONREAL_LIVE_CONN_INTERVAL 4*60 /* Default: 4*60=4 minutes */ +#define REMOVE_LIVE_CONN_INTERVAL 8*3600 /* Default: 8*3600=8 hours */ +#define REMOVE_CLOSED_CONN_INTERVAL 8*60 /* Default: 8*60=8 minutes */ +#define UPDATE_INTERVAL 30 /* Default: 30 seconds */ +#define MAX_CONN_NUM 50000 /* Default: 50000 max number of connections */ + +/*BEGIN:FV*/ +/*Check Interval: Default: 180*/ +#define TIMEOUT_INTERVAL 60 +/*Timeout value to check the closed connections. Default: 300 sec timeout */ +#define CONNECTION_TIMEOUT 300 +/*END:FV*/ + + /* for continuous mode */ /* minimal support for UDP "connections" */ @@ -676,6 +738,15 @@ /* option flags */ extern Bool colorplot; extern Bool dump_rtt; + +/*BEGIN:FV*/ +extern Bool dump_rtt_global; +static MFILE *rtt_dump_file_global; +extern char *rtt_output_filename; +extern Bool print_timeout; +extern Bool print_timeout_dump; +/*END:FV*/ + extern Bool graph_rtt; extern Bool graph_tput; extern Bool graph_tsg; @@ -809,6 +880,11 @@ void plotter_switch_axis(PLOTTER, Bool); void plot_init(void); tcp_pair *dotrace(struct ip *, struct tcphdr *ptcp, void *plast); +/*BEGIN:FV*/ +//tcp_pair *DumpClosedConns(struct ip *pip,struct tcphdr *ptcp,tcp_pair *ptp_save); +void DumpConnection(tcp_pair *ptp_save); +/*END:FV*/ + void PrintRawData(char *label, void *pfirst, void *plast, Bool octal); void PrintRawDataHex(char *label, void *pfirst, void *plast); void PrintTrace(tcp_pair *); @@ -843,6 +919,13 @@ int rexmit(tcb *, seqnum, seglen, Bool *); enum t_ack ack_in(tcb *, seqnum, unsigned tcp_data_length, u_long eff_win); Bool IsRTO(tcb *ptcb, seqnum s); +/*BEGIN:FV +New Function to check if the RTO is spurious*/ +int IsSRTO(tcb *ptcb, seqnum s, int segtime); +/*New function to check outof order packets*/ +int IsOOO(tcb *ptcb, seqnum s); +/*END:FV*/ + void DoThru(tcb *ptcb, int nbytes); struct mfile *Mfopen(char *fname, char *mode); void Minit(void); diff -Naur tcptrace-6.6.7/trace.c tcptrace-6.6.7_4.ftw/trace.c --- tcptrace-6.6.7/trace.c 2004-11-04 23:43:51.000000000 +0100 +++ tcptrace-6.6.7_4.ftw/trace.c 2005-02-22 15:15:08.000000000 +0100 @@ -77,8 +77,11 @@ static int tline_right = 0; /* provided globals */ -int num_tcp_pairs = -1; /* how many pairs we've allocated */ +int num_tcp_pairs = -1; /* how many pairs we've seen */ +int num_active_tcp_pairs = -1; /* how many pairs we've allocated */ + tcp_pair **ttp = NULL; /* array of pointers to allocated pairs */ +Bool *dumped_pairs=NULL; /*BEGIN:FV Added*/ int max_tcp_pairs = 64; /* initial value, automatically increases */ u_long tcp_trace_count = 0; @@ -116,6 +119,7 @@ Bool nonames = FALSE; Bool use_short_names = FALSE; Bool show_urg = TRUE; +Bool first = TRUE; int thru_interval = 10; /* in segments */ @@ -505,16 +509,33 @@ printf("trace.c:NewTTP() calling MakeTcpPair()\n"); } ptp = MakeTcpPair(); - ++num_tcp_pairs; - + + if (!run_continuously) { + int i; /* make a new one, if possible */ - if ((num_tcp_pairs+1) >= max_tcp_pairs) { - MoreTcpPairs(num_tcp_pairs+1); - } + if ((num_active_tcp_pairs+1) >= max_tcp_pairs) { + MoreTcpPairs(num_active_tcp_pairs+1); + i=num_active_tcp_pairs; + if (1) fprintf(stderr,"maxconn: %lu activeconn: %lu tcpconn: %lu\n",max_tcp_pairs,num_active_tcp_pairs,num_tcp_pairs); + }else i=0; /* create a new TCP pair record and remember where you put it */ - ttp[num_tcp_pairs] = ptp; - ptp->ignore_pair = ignore_pairs[num_tcp_pairs]; + + for (;i<=num_active_tcp_pairs;i++){ + if (dumped_pairs[i]==TRUE) + break; + } + + + ++num_tcp_pairs; + ++num_active_tcp_pairs; + + ttp[i] = ptp; + dumped_pairs[i]=FALSE; + ptp->ttp_number=i; + ptp->connection_number=num_tcp_pairs; + ptp->ignore_pair = FALSE; + ptp->closed_conn = 0; } @@ -556,6 +577,28 @@ ptp->a2b.LEAST = ptp->b2a.LEAST = 0; ptp->a2b.in_rto = ptp->b2a.in_rto = FALSE; + /* BEGIN:FV */ + + ptp->a2b.in_srto = ptp->b2a.in_srto = FALSE; + ptp->a2b.in_nrto = ptp->b2a.in_nrto = FALSE; + ptp->a2b.in_frtx = ptp->b2a.in_frtx = FALSE; + ptp->a2b.rtx_during_srto = ptp->b2a.rtx_during_srto = 0; + ptp->a2b.rtx_during_nrto = ptp->b2a.rtx_during_nrto = 0; + ptp->a2b.rtx_during_frtx = ptp->b2a.rtx_during_frtx = 0; + + /* Statistics */ + + ptp->a2b.stat_spurious_rto = ptp->b2a.stat_spurious_rto = 0; + ptp->a2b.stat_normal_rto = ptp->b2a.stat_normal_rto = 0; + ptp->a2b.stat_ambiguos_rto = ptp->b2a.stat_ambiguos_rto = 0; + ptp->a2b.stat_fast_rexmit = ptp->b2a.stat_fast_rexmit = 0; + ptp->a2b.stat_rtx_during_srto = ptp->b2a.stat_rtx_during_srto = 0; + ptp->a2b.stat_rtx_during_nrto = ptp->b2a.stat_rtx_during_nrto = 0; + ptp->a2b.stat_rtx_during_frtx = ptp->b2a.stat_rtx_during_frtx = 0; + + /* END:FV */ + + /* init time sequence graphs */ ptp->a2b.tsg_plotter = ptp->b2a.tsg_plotter = NO_PLOTTER; if (graph_tsg && !ptp->ignore_pair) { @@ -838,8 +881,8 @@ if (ptp->inactive) { if (!run_continuously) - continue; - else { + return NULL; + else { *tcp_ptr = (ptp_ptr *)ptph->ptp; return ((*tcp_ptr)->ptp); } @@ -883,6 +926,7 @@ SEQ_LESSTHAN(ntohl(ptcp->th_seq),thisdir->syn)); } + if (0) /*BEGIN:FV Removed*/ if (/* rule 1 */ (elapsed(ptp->last_time,current_time)/1000000 > nonreal_live_conn_interval)//(4*60)) - Using nonreal_live_conn_interval instead of the 4 mins heuristic || /* rule 2 */ @@ -918,7 +962,9 @@ FindTTP() calling SnapRemove()\n"); /* Removes connection snapshot from AVL tree */ - SnapRemove(pptph_head, ptph->addr_pair); + DumpConnection(ptp); + + break; } @@ -1406,6 +1452,13 @@ th_urp = ntohs(ptcp->th_urp); ip_len = gethdrlength(pip, plast) + getpayloadlength(pip,plast); + + /*BEGIN:FV + * Hard Filter to avoid spurious traffic on SAMBA services (port 135 and 445)*/ + + if ((1)&&(th_sport==445||th_dport==445||th_sport==135||th_dport==135)) + return NULL; + /*END:FV*/ /* make sure this is one of the connections we want */ ptp_save = FindTTP(pip,ptcp,&dir, &tcp_ptr); @@ -1490,7 +1543,7 @@ /* calc. data range */ start = th_seq; end = start + tcp_data_length; - + u_long segtime = (u_long)(elapsed(ptp_save->first_time,current_time)/1000000); /* seq. space wrap around stats */ /* If all four quadrants have been visited and the current packet * is in the same quadrant as the syn, check if latest seq. num is @@ -1770,9 +1823,79 @@ } else retrans_cnt = retrans_num_bytes = rexmit(thisdir,start, len, &out_order); - - if (out_order) + + /*BEGIN:FV*/ + if (out_order){ + int isooo=IsOOO(thisdir, th_seq); + + switch (isooo) { + case 0: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s AMBIGUOS OUTOFORDER from %lu to %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)start, (u_long) end, segtime); + } + else fprintf(stdout,"%s:%s AMBIGUOS OUTOFORDER from %lu to %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)start, (u_long) end, segtime); + break; + case 1: + if (thisdir->in_srto){ + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s RTX DURING sRTO NOT SPURIOUS from %lu to %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)start, (u_long) end, segtime); + } + else fprintf(stdout,"%s:%s RTX DURING sRTO NOT SPURIOUS from %lu to %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)start, (u_long) end, segtime); + + thisdir->rtx_during_srto++; + } + else if (thisdir->in_nrto){ + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s RTX DURING nRTO NOT SPURIOUS from %lu to %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)start, (u_long) end, segtime); + } + else fprintf(stdout,"%s:%s RTX DURING nRTO NOT SPURIOUS from %lu to %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)start, (u_long) end, segtime); + + thisdir->rtx_during_nrto++; + } + else { + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s OUTOFORDER from %lu to %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)start, (u_long) end, segtime); + } + else fprintf(stdout,"%s:%s OUTOFORDER from %lu to %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)start, (u_long) end, segtime); + } + break; + case 2: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s FAST RETRANSMIT OOO from %lu to %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)start, (u_long) end, segtime); + } + else fprintf(stdout,"%s:%s FAST RETRANSMIT OOO from %lu to %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)start, (u_long) end, segtime); + + thisdir->stat_fast_rexmit++; + break; + } ++thisdir->out_order_pkts; + } + /*END:FV*/ /* count anything NOT retransmitted as "unique" */ /* exclude SYN and FIN */ @@ -1809,8 +1932,14 @@ otherdir->lastackno = th_ack; } - /* LEAST */ - if (thisdir->tcp_strain == TCP_RENO) { + /* changes by thomas ziegler: + * detect RTOs for reno and sack and distinguish between normal and spurious RTOs + */ + + + + + if (thisdir->tcp_strain == TCP_RENO || thisdir->tcp_strain == TCP_SACK) { if (thisdir->in_rto && tcp_data_length > 0) { if (retrans_num_bytes>0 && th_seq < thisdir->recovered) thisdir->event_retrans++; @@ -1821,15 +1950,137 @@ if (!(retrans_num_bytes>0) && thisdir->ack <= thisdir->recovered_orig) thisdir->recovered = th_seq; } - if (otherdir->in_rto && ACK_SET(ptcp)) { - if (th_ack > otherdir->recovered) { - otherdir->LEAST -= - (otherdir->event_dupacks < otherdir->event_retrans)? - otherdir->event_dupacks:otherdir->event_retrans; - otherdir->in_rto = FALSE; - } else if (th_ack == otherdir->lastackno && - th_ack >= otherdir->rto_segment) otherdir->event_dupacks++; + + + /*BEGIN:FV Experimental*/ + if (thisdir->in_frtx && tcp_data_length > 0) { + if (!(retrans_num_bytes>0) && otherdir->ack <= thisdir->frecovered_orig) { + thisdir->frecovered = th_seq; + //if (print_timeout_dump) + //fprintf(stdout,"ack: %lu frecovered: %lu frecovered_orig %lu \n",otherdir->ack,thisdir->frecovered,thisdir->frecovered_orig); + } + } + if (thisdir->in_srto && tcp_data_length > 0) { + if (!(retrans_num_bytes>0) && otherdir->ack <= thisdir->srecovered_orig) { + thisdir->srecovered = th_seq; + //if (print_timeout_dump) + //fprintf(stdout,"ack: %lu srecovered: %lu srecovered_orig %lu \n",otherdir->ack,thisdir->srecovered,thisdir->srecovered_orig); + } } + if (thisdir->in_nrto && tcp_data_length > 0) { + if (!(retrans_num_bytes>0) && otherdir->ack <= thisdir->nrecovered_orig) { + thisdir->nrecovered = th_seq; + //if (print_timeout_dump) + //fprintf(stdout,"ack: %lu nrecovered: %lu nrecovered_orig %lu \n",otherdir->ack,thisdir->nrecovered,thisdir->nrecovered_orig); + } + } + /*END:FV*/ + + if (ACK_SET(ptcp)) { + /* other dir in normal rto state */ + if (otherdir->in_rto) { + if (th_ack >= otherdir->recovered) { + otherdir->LEAST -= + (otherdir->event_dupacks < otherdir->event_retrans)? + otherdir->event_dupacks:otherdir->event_retrans; + otherdir->in_rto = FALSE; + } else if (th_ack == otherdir->lastackno && th_ack >= otherdir->rto_segment) + otherdir->event_dupacks++; + } + + /*BEGIN:FV*/ + if ((otherdir->in_srto) || (otherdir->in_nrto) || (otherdir->in_frtx)) { + if (otherdir->in_srto){ + /* other dir in "maybe srto" state */ + if (th_ack >= otherdir->srecovered) { + //if (otherdir->rtx_during_srto) { + otherdir->stat_spurious_rto++; + otherdir->stat_rtx_during_srto+=otherdir->rtx_during_srto; + if (print_timeout_dump) + if (!strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s CONFIRMED sRTO seqno %lu with ack %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)otherdir->srto_segment,(u_long)th_ack,segtime); + } + else fprintf(stdout,"%s:%s CONFIRMED sRTO seqno %lu with ack %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)otherdir->srto_segment,(u_long)th_ack,segtime); + + /* This anbiguos feature has beed eliminated + } + else { + if (print_timeout_dump) + fprintf(stdout,"trace: CLEARED sRTO (1) seqno %lu with ack %lu at %d sec\n", + (u_long)otherdir->srto_segment,(u_long)th_ack,segtime); + otherdir->stat_ambiguos_rto++; + } + */ + + otherdir->in_srto = FALSE; + + } + else if (th_ack == otherdir->srto_segment) { + otherdir->in_srto = FALSE; + otherdir->in_nrto = TRUE; + otherdir->nrecovered=otherdir->srecovered; + otherdir->nrecovered_orig=otherdir->srecovered_orig; + otherdir->rtx_during_nrto=otherdir->rtx_during_srto; + if (print_timeout_dump) + if (!strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s CLEARED sRTO (0) ENTER sRTO seqno %lu with ack %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)otherdir->srto_segment,(u_long)th_ack,segtime); + } + else fprintf(stdout,"%s:%s CLEARED sRTO (0) ENTER sRTO seqno %lu with ack %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)otherdir->srto_segment,(u_long)th_ack,segtime); + + } + } + if (otherdir->in_nrto){ + /* other dir in normal timeout state */ + if (th_ack >= otherdir->nrecovered) { + otherdir->stat_normal_rto++; + otherdir->stat_rtx_during_nrto+=otherdir->rtx_during_nrto; + otherdir->in_nrto = FALSE; + if (print_timeout_dump) + if (!strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s EXIT nRTO nrecovered %lu with ack %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)otherdir->nrecovered,(u_long)th_ack,segtime); + } + else fprintf(stdout,"%s:%s EXIT nRTO nrecovered %lu with ack %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)otherdir->nrecovered,(u_long)th_ack,segtime); + + } + + } + if (otherdir->in_frtx){ + /* other dir in fast_retransmit state */ + if (th_ack >= otherdir->frecovered) { + otherdir->stat_rtx_during_frtx+=otherdir->rtx_during_frtx; + otherdir->in_frtx = FALSE; + if (print_timeout_dump) + if (!strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s EXIT FRTX frecovered %lu with ack %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)otherdir->frecovered,(u_long)th_ack,segtime); + } + else fprintf(stdout,"%s:%s EXIT FRTX frecovered %lu with ack %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)otherdir->frecovered,(u_long)th_ack,segtime); + } + + } + + + } + /*END:FV*/ + + } + + } /* plot out-of-order segments, if asked */ @@ -1844,16 +2095,163 @@ } /* stats for rexmitted data */ + /* changes by thomas ziegler */ if (retrans_num_bytes>0) { retrans = TRUE; /* for reno LEAST estimate */ - if (thisdir->tcp_strain == TCP_RENO && - !thisdir->in_rto && IsRTO(thisdir, th_seq)) { - thisdir->in_rto = TRUE; - thisdir->recovered = thisdir->recovered_orig = thisdir->seq; - thisdir->rto_segment = th_seq; - thisdir->event_retrans = 1; thisdir->event_dupacks = 0; - } + if ((thisdir->tcp_strain == TCP_RENO || thisdir->tcp_strain == TCP_SACK)) { + if (!thisdir->in_rto && IsRTO(thisdir, th_seq)) { + thisdir->in_rto = TRUE; + thisdir->recovered = thisdir->recovered_orig = thisdir->seq; + thisdir->rto_segment = th_seq; + thisdir->event_retrans = 1; thisdir->event_dupacks = 0; + } + + + int srto_type=IsSRTO(thisdir, th_seq, segtime); + + + + if (thisdir->in_srto || thisdir->in_nrto || thisdir->in_frtx){ + if (thisdir->in_srto){ + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s RTX DURING sRTO from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s RTX DURING sRTO from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + thisdir->rtx_during_srto++; + } + if (thisdir->in_nrto) { + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s RTX DURING nRTO from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s RTX DURING nRTO from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + + thisdir->rtx_during_nrto++; + } + if (thisdir->in_frtx) { + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s RTX DURING FRECOVERY from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s RTX DURING FRECOVERY from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + thisdir->rtx_during_frtx++; + } + } + else{ + switch (srto_type) { + case 0: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s FAST RETRANSMIT from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s FAST RETRANSMIT from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + break; + case 1: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s NORMAL TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s NORMAL TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + break; + case 2: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s SPURIOUS TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s SPURIOUS TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + break; + case 3: + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s SPURIOUS SACK TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s SPURIOUS SACK TIMEOUT from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + + break; + } + + } + if (!thisdir->in_srto && !thisdir->in_nrto && !thisdir->in_frtx) { + if ((srto_type==2)||(srto_type==3)) { + if (thisdir->seq>end){ + //last byte of the retransmitted packet + thisdir->srto_segment_end = end; + //first byte of the retransmitted packet + thisdir->srto_segment = th_seq; + //the last byte of the outstanding data + thisdir->srecovered = thisdir->srecovered_orig = thisdir->seq; + //fprintf(stdout,"trace: srecovered %lu\n",(u_long)thisdir->srecovered); + thisdir->in_srto = TRUE; + thisdir->rtx_during_srto = 0; + } + else { + thisdir->stat_ambiguos_rto++; + if (print_timeout_dump) + if (strcmp(thisdir->host_letter,(&thisdir->ptp->a2b)->host_letter)){ + fprintf(stdout,"%s:%s CLEARED sRTO (2) from byte %lu to byte %lu at %d\n", + thisdir->ptp->a_hostname,thisdir->ptp->a_portname, + (u_long)th_seq,(u_long)end,segtime); + } + else fprintf(stdout,"%s:%s CLEARED sRTO (2) from byte %lu to byte %lu at %d\n", + thisdir->ptp->b_hostname,thisdir->ptp->b_portname, + (u_long)th_seq,(u_long)end,segtime); + } + } + if (srto_type==1){ + //last byte of the retransmitted packet + thisdir->nrto_segment_end = end; + //first byte of the retransmitted packet + thisdir->nrto_segment = th_seq; + //the last byte of the outstanding data + thisdir->nrecovered = thisdir->nrecovered_orig = thisdir->seq; + thisdir->in_nrto = TRUE; + thisdir->rtx_during_nrto = 0; + } + if (srto_type==0){ + thisdir->stat_fast_rexmit++; + thisdir->frecovered = thisdir->frecovered_orig = thisdir->seq; + thisdir->in_frtx=TRUE; + thisdir->rtx_during_frtx = 0; + } + } + + } thisdir->rexmit_pkts += 1; thisdir->LEAST++; thisdir->rexmit_bytes += retrans_num_bytes; @@ -1870,8 +2268,18 @@ "c", hw_dup?"HD":"R"); } } else { + + + + + /*BEGIN:FV + It this correct? Is thisdir->seq the last byte seen? + If not it is correct otherwise it is wrong + */ + if (thisdir->seq < end) thisdir->seq = end; - } + /*END:FV*/ + } if(probe) { if(from_tsgpl != NO_PLOTTER && show_zwnd_probes){ @@ -2468,12 +2876,334 @@ if (run_continuously) { UpdateConnLists(tcp_ptr, ptcp); } - + + /*BEGIN:FV + Added here to keep track of the packets received after 2 FYN*/ + if ((FinCount(ptp_save) >= 2)){ + ptp_save->closed_conn++; + } + /*END:FV*/ + return(ptp_save); } +/*BEGIN:FV UNUSED FUNCTION +tcp_pair *DumpClosedConns( + struct ip *pip, + struct tcphdr *ptcp, + tcp_pair *ptp_save) +{ + In this point the connection should be totally removed and statistics printed out + ptp_snap **pptph_head = NULL; + ptp_snap *ptph; + tcp_pair_addrblock tp_in; + int dir, conn_status,i; + hash hval; + + + if (!ptp_save->ignore_pair) { + if ((printbrief) && (!ignore_non_comp || ConnComplete(ptp_save))) { + fprintf(stdout,"%3d: ", ptp_save->ttp_number+1); + PrintBrief(ptp_save); + } else if (!ignore_non_comp || ConnComplete(ptp_save)) { + if(csv || tsv || (sv != NULL)) { + if(first) { + PrintSVHeader(); + first = FALSE; + } + fprintf(stdout, "%d%s", ptp_save->ttp_number+1, sp); + fprintf(stdout, "%s", sp); + } + else { + if (ptp_save->ttp_number > 0) + fprintf(stdout,"================================\n"); + fprintf(stdout,"TCP connection %d:\n", ptp_save->ttp_number+1); + + } + PrintTrace(ptp_save); + } + + + //ptp_save->inactive=TRUE; + + free(ptp_save->a2b.host_letter); + free(ptp_save->b2a.host_letter); + free(ptp_save->a_hostname); + free(ptp_save->a_portname); + free(ptp_save->a_endpoint); + free(ptp_save->b_hostname); + free(ptp_save->b_portname); + free(ptp_save->b_endpoint); + + if (ptp_save->a2b.owin_line) { + free(ptp_save->a2b.owin_line); + } + + if (show_rwinline) { + if (ptp_save->a2b.rwin_line) { + free(ptp_save->a2b.rwin_line); + } + } + + if (ptp_save->a2b.owin_avg_line) { + free(ptp_save->a2b.owin_avg_line); + } + if (ptp_save->a2b.owin_wavg_line) { + free(ptp_save->a2b.owin_avg_line); + } + if (ptp_save->b2a.owin_line) { + free(ptp_save->b2a.owin_line); + } + + if (show_rwinline) { + if (ptp_save->b2a.rwin_line) { + free(ptp_save->b2a.rwin_line); + } + } + + if (ptp_save->b2a.owin_avg_line) { + free(ptp_save->b2a.owin_avg_line); + } + if (ptp_save->b2a.owin_wavg_line) { + free(ptp_save->b2a.owin_wavg_line); + } + + if (ptp_save->a2b.segsize_line) { + free(ptp_save->a2b.segsize_line); + } + if (ptp_save->a2b.segsize_avg_line) { + free(ptp_save->a2b.segsize_avg_line); + } + if (ptp_save->b2a.segsize_line) { + free(ptp_save->b2a.segsize_line); + } + if (ptp_save->b2a.segsize_avg_line) { + free(ptp_save->b2a.segsize_avg_line); + } + if (ptp_save->a2b.ss) { + for (i = 0; i < 4; i++) { + if (ptp_save->a2b.ss->pquad[i] != NULL) { + freequad(&ptp_save->a2b.ss->pquad[i]); + } + } + FreeSeqspace(ptp_save->a2b.ss); + } + + if (ptp_save->b2a.ss) { + for (i = 0; i < 4; i++) { + if (ptp_save->b2a.ss->pquad[i] != NULL) { + freequad(&ptp_save->b2a.ss->pquad[i]); + } + } + FreeSeqspace(ptp_save->b2a.ss); + } + + + + dumped_pairs[ptp_save->ttp_number]=TRUE; + + + CopyAddr(&tp_in, pip, ntohs(ptcp->th_sport), ntohs(ptcp->th_dport)); + + hval = tp_in.hash % HASH_TABLE_SIZE; + + pptph_head = &ptp_hashtable[hval]; + + for (ptph = *pptph_head; ptph; ) { + dir = WhichDir(&tp_in, &ptph->addr_pair); + if (dir == A2B || dir == B2A) { + SnapRemove(pptph_head, ptph->addr_pair); + break; + } + else { // WhichDir returned 0, meaning if it exists, it's deeper + conn_status = AVL_WhichDir(&tp_in,&ptph->addr_pair); + if (conn_status == LT) + ptph = ptph->left; + else if (conn_status == RT) + ptph = ptph->right; + else if (!conn_status) { + fprintf(stderr, "WARNING!! AVL_WhichDir() should not return 0 if\n" + "\tWhichDir() didn't return A2B or B2A previously\n"); + break; + } + } + } + + ptp_save->a2b.ptwin=NULL; + ptp_save->a2b.ptp=NULL; + ptp_save->b2a.ptp=NULL; + ptp_save->b2a.ptwin=NULL; + FreeTcpPair(ptp_save); + ptp_save = NULL; + + } + return ptp_save; +} +*/ +/*BEGIN:FV Eliminate and Dump on the output the ptp_save connection*/ + +void DumpConnection(tcp_pair *ptp_save) +{ + ptp_snap **pptph_head = NULL; + ptp_snap *ptph; + tcp_pair_addrblock tp_in; + int dir, conn_status,i; + hash hval; + + + if (!ptp_save->ignore_pair) { + if ((printbrief) && (!ignore_non_comp || ConnComplete(ptp_save))) { + fprintf(stdout,"%3d: ", ptp_save->connection_number+1); + PrintBrief(ptp_save); + } else if (!ignore_non_comp || ConnComplete(ptp_save)) { + if(csv || tsv || (sv != NULL)) { + if(first) { + PrintSVHeader(); + first = FALSE; + } + fprintf(stdout, "%d%s", ptp_save->connection_number+1, sp); + fprintf(stdout, "%s", sp); + } + else { + if (ptp_save->ttp_number > 0) + fprintf(stdout,"================================\n"); + fprintf(stdout,"TCP connection %d:\n", ptp_save->connection_number+1); + + } + PrintTrace(ptp_save); + } + + + //ptp_save->inactive=TRUE; + + free(ptp_save->a2b.host_letter); + free(ptp_save->b2a.host_letter); + free(ptp_save->a_hostname); + free(ptp_save->a_portname); + free(ptp_save->a_endpoint); + free(ptp_save->b_hostname); + free(ptp_save->b_portname); + free(ptp_save->b_endpoint); + + if (ptp_save->a2b.owin_line) { + free(ptp_save->a2b.owin_line); + } + + if (show_rwinline) { + if (ptp_save->a2b.rwin_line) { + free(ptp_save->a2b.rwin_line); + } + } + + if (ptp_save->a2b.owin_avg_line) { + free(ptp_save->a2b.owin_avg_line); + } + if (ptp_save->a2b.owin_wavg_line) { + free(ptp_save->a2b.owin_avg_line); + } + if (ptp_save->b2a.owin_line) { + free(ptp_save->b2a.owin_line); + } + + if (show_rwinline) { + if (ptp_save->b2a.rwin_line) { + free(ptp_save->b2a.rwin_line); + } + } + + if (ptp_save->b2a.owin_avg_line) { + free(ptp_save->b2a.owin_avg_line); + } + if (ptp_save->b2a.owin_wavg_line) { + free(ptp_save->b2a.owin_wavg_line); + } + + if (ptp_save->a2b.segsize_line) { + free(ptp_save->a2b.segsize_line); + } + if (ptp_save->a2b.segsize_avg_line) { + free(ptp_save->a2b.segsize_avg_line); + } + if (ptp_save->b2a.segsize_line) { + free(ptp_save->b2a.segsize_line); + } + if (ptp_save->b2a.segsize_avg_line) { + free(ptp_save->b2a.segsize_avg_line); + } + if (ptp_save->a2b.ss) { + for (i = 0; i < 4; i++) { + if (ptp_save->a2b.ss->pquad[i] != NULL) { + freequad(&ptp_save->a2b.ss->pquad[i]); + } + } + FreeSeqspace(ptp_save->a2b.ss); + } + + if (ptp_save->b2a.ss) { + for (i = 0; i < 4; i++) { + if (ptp_save->b2a.ss->pquad[i] != NULL) { + freequad(&ptp_save->b2a.ss->pquad[i]); + } + } + FreeSeqspace(ptp_save->b2a.ss); + } + + + + dumped_pairs[ptp_save->ttp_number]=TRUE; + --num_active_tcp_pairs; + + + /* grab the address from this the ptp */ + tp_in=ptp_save->addr_pair; + + /* grab the hash value (already computed by CopyAddr) */ + hval = tp_in.hash % HASH_TABLE_SIZE; + + pptph_head = &ptp_hashtable[hval]; + + int i=pools[0].block_no; + for (ptph = *pptph_head; ptph; ) { + dir = WhichDir(&tp_in, &ptph->addr_pair); + if (dir == A2B || dir == B2A) { + + //if (((*pptph_head)->right==NULL)&&((*pptph_head)->left==NULL)) + //ptp_hashtable[hval]=NULL; + //ptp_snap *temp=&ptph; + + SnapRemove(pptph_head, ptph->addr_pair); + + //FreePtpSnap(temp); + + break; + } + else { // WhichDir returned 0, meaning if it exists, it's deeper + conn_status = AVL_WhichDir(&tp_in,&ptph->addr_pair); + if (conn_status == LT) + ptph = ptph->left; + else if (conn_status == RT) + ptph = ptph->right; + else if (!conn_status) { + fprintf(stderr, "WARNING!! AVL_WhichDir() should not return 0 if\n" + "\tWhichDir() didn't return A2B or B2A previously\n"); + break; + } + } + } + int j=pools[0].block_no; + ptp_save->a2b.ptwin=NULL; + ptp_save->a2b.ptp=NULL; + ptp_save->b2a.ptp=NULL; + ptp_save->b2a.ptwin=NULL; + FreeTcpPair(ptp_save); + ptp_save = NULL; + + } +} + + void trace_done(void) { @@ -2547,31 +3277,33 @@ } /* complete the "idle time" calculations using NOW */ - for (ix = 0; ix <= num_tcp_pairs; ++ix) { - tcp_pair *ptp = ttp[ix]; - tcb *thisdir; - u_llong itime; - - /* if it's CLOSED, skip it */ - if ((FinCount(ptp)>=2) || (ConnReset(ptp))) - continue; - - /* a2b direction */ - thisdir = &ptp->a2b; - if (!ZERO_TIME(&thisdir->last_time)) { - itime = elapsed(thisdir->last_time,current_time); - if (itime > thisdir->idle_max) - thisdir->idle_max = itime; - } - - - /* b2a direction */ - thisdir = &ptp->b2a; - if (!ZERO_TIME(&thisdir->last_time)) { - itime = elapsed(thisdir->last_time,current_time); - if (itime > thisdir->idle_max) - thisdir->idle_max = itime; - } + for (ix = 0; ix <= num_active_tcp_pairs; ++ix) { + if (dumped_pairs[ix]==FALSE){ + tcp_pair *ptp = ttp[ix]; + tcb *thisdir; + u_llong itime; + + /* if it's CLOSED, skip it */ + if ((FinCount(ptp)>=2) || (ConnReset(ptp))) + continue; + + /* a2b direction */ + thisdir = &ptp->a2b; + if (!ZERO_TIME(&thisdir->last_time)) { + itime = elapsed(thisdir->last_time,current_time); + if (itime > thisdir->idle_max) + thisdir->idle_max = itime; + } + + + /* b2a direction */ + thisdir = &ptp->b2a; + if (!ZERO_TIME(&thisdir->last_time)) { + itime = elapsed(thisdir->last_time,current_time); + if (itime > thisdir->idle_max) + thisdir->idle_max = itime; + } + } } } @@ -2588,16 +3320,16 @@ if (filter_output) { if (!run_continuously) { /* mark the connections to ignore */ - for (ix = 0; ix <= num_tcp_pairs; ++ix) { + for (ix = 0; ix <= num_active_tcp_pairs; ++ix) { ptp = ttp[ix]; if (PassesFilter(ptp)) { if (++count == 1) - fprintf(f_passfilter,"%d", ix+1); + fprintf(f_passfilter,"%d", ptp->connection_number+1); else - fprintf(f_passfilter,",%d", ix+1); + fprintf(f_passfilter,",%d", ptp->connection_number+1); } else { /* else ignore it */ - ptp->ignore_pair = TRUE; + ptp->ignore_pair = FALSE; //BEGIN:FV TRUE; } } } @@ -2607,15 +3339,16 @@ if (!run_continuously) { /* print each connection */ if (!printsuppress) { - Bool first = TRUE; /* Used with -separated-values + /*Bool first = TRUE; Used with -separated-values * Keeps track of whether header has already * been printed */ - for (ix = 0; ix <= num_tcp_pairs; ++ix) { - ptp = ttp[ix]; + for (ix = 0; ix <= num_active_tcp_pairs; ++ix) { + if (dumped_pairs[ix]==FALSE){ + ptp = ttp[ix]; if (!ptp->ignore_pair) { if ((printbrief) && (!ignore_non_comp || ConnComplete(ptp))) { - fprintf(stdout,"%3d: ", ix+1); + fprintf(stdout,"%3d: ", ptp->connection_number+1); PrintBrief(ptp); } else if (!ignore_non_comp || ConnComplete(ptp)) { if(csv || tsv || (sv != NULL)) { @@ -2623,7 +3356,8 @@ PrintSVHeader(); first = FALSE; } - fprintf(stdout, "%d%s", ix+1, sp); + fprintf(stdout, "%d%s", ptp->connection_number+1, sp); + fprintf(stdout, "%s", sp); } else { if (ix > 0) @@ -2640,9 +3374,9 @@ if (ignore_non_comp) if (ConnComplete(ptp)) { if (++count == 1) - fprintf(f_passfilter, "%d", ix+1); + fprintf(f_passfilter, "%d", ptp->connection_number+1); else - fprintf(f_passfilter, ",%d", ix+1); + fprintf(f_passfilter, ",%d", ptp->connection_number+1); } /******************************/ @@ -2655,6 +3389,7 @@ } } } +} } /* if we're filtering, close the file */ @@ -2682,9 +3417,16 @@ if (num_needed < max_tcp_pairs) return; - new_max_tcp_pairs = max_tcp_pairs * 4; - while (new_max_tcp_pairs < num_needed) - new_max_tcp_pairs *= 4; + /*BEGIN:FV Originally it was *4 factor! */ + if (max_tcp_pairs<131072){ + new_max_tcp_pairs = max_tcp_pairs * 2; + while (new_max_tcp_pairs < num_needed) + new_max_tcp_pairs *= 2; + }else{ + new_max_tcp_pairs = max_tcp_pairs + 16384; + while (new_max_tcp_pairs < num_needed) + new_max_tcp_pairs += 16384; + } if (debug) printf("trace: making more space for %d total TCP pairs\n", @@ -2699,10 +3441,20 @@ ignore_pairs = ReallocZ(ignore_pairs, max_tcp_pairs * sizeof(Bool), new_max_tcp_pairs * sizeof(Bool)); + + /* enlarge array to keep track of which ones already dumped */ + dumped_pairs = ReallocZ(dumped_pairs, + max_tcp_pairs * sizeof(Bool), + new_max_tcp_pairs * sizeof(Bool)); + if (more_conns_ignored) - for (i=max_tcp_pairs; i < new_max_tcp_pairs;++i) + for (i=max_tcp_pairs; i < new_max_tcp_pairs;++i){ ignore_pairs[i] = TRUE; - + dumped_pairs[i] = TRUE; + } + for (i=max_tcp_pairs; i < new_max_tcp_pairs;++i){ + dumped_pairs[i] = TRUE; + } max_tcp_pairs = new_max_tcp_pairs; } @@ -2738,13 +3490,14 @@ /* create an array to keep track of which ones to ignore */ ignore_pairs = (Bool *) MallocZ(max_tcp_pairs * sizeof(Bool)); - if (!run_continuously) { - /* create an array to hold any pairs that we might create */ + dumped_pairs = (Bool *) MallocZ(max_tcp_pairs * sizeof(Bool)); + /*if (!run_continuously) { + /* create an array to hold any pairs that we might create ttp = (tcp_pair **) MallocZ(max_tcp_pairs * sizeof(tcp_pair *)); - /* create an array to keep track of which ones to ignore */ + /* create an array to keep track of which ones to ignore ignore_pairs = (Bool *) MallocZ(max_tcp_pairs * sizeof(Bool)); - } + }*/ cainit(); Minit();