#!/usr/local/bin/perl # tsh2ta.pl -f filename {-i interface} {-d displayflags} {-a alpha} {-t init_timeout} {-x exit time} {-b} # {-s smallflow packets} {-m mediumflow packets} {-h alpha long} # New timeout value = max interarrival time * L?h:k ### sections denoted by three comment characters (###) are modifications ### made by David Cheney for specific purposes related to timeout ### research with Bo Ryu and Hans-Werner Braun. ### $boff=2; # default for the number of backoffs @pkt_th = (10,6,3); # default packet threshold for each timeout ### $tdelta=1; # synchronous array evaluation timeout in seconds $tout_low = 4; # default lowest flow timeout in seconds $etime=9e99; # forxed exit time in seconds #------------------------------------------------------------------------------- # command line parser while(($id,@r)=split('=',$ARGV[$argc++])){ if($id =~ "f"){ # input file name $I=$ARGV[$argc++]; open(infile,$I) || die("Can't open input file\n"); # open(infile,"gzip -dc $I |") || die("Can't open input file\n"); }elsif($id =~ "t"){ # lowest (beginning) flow timeout $tout_low=$ARGV[$argc++]; }elsif($id =~ "i"){ # input interface number $interface=$ARGV[$argc++]; }elsif($id =~ "r"){ # number of exponential backoffs $boff=$ARGV[$argc++]; }elsif($id =~ "m"){ # packet threshold for each timeout value @pkt_th = split(',' ,$ARGV[$argc++]); }elsif($id =~ "d"){ # display flags $DISPLAY=$ARGV[$argc++]; }elsif($id =~ "x"){ # end time (for percentile cut) $etime=$ARGV[$argc++]; }elsif($id =~ "b"){ # bidirectional flows (transactions) $bflag++; }else{ printf stderr "Usage: $0 -f fname (-i #} {-d flags} {-x exit time} {-b} {-t lowest_timeout} {-r backoffs} {-m pkt_thresold (,,,)}\n"; exit(1); } } if(!$I){ printf stderr "Usage: $0 -f fname (-i #} {-d flags} {-x exit time} {-b} {-t lowest_timeout} {-r backoffs} {-m pkt_thresold (,,,)}\n"; exit(1); } if($#pkt_th != $boff){ printf stderr "Number of backoffs ($boff) does not match the number of packet thresholds\n"; exit(1); } # print command line parameters printf "P\t"; $argc=0; while(($id,@r)=split('=',$ARGV[$argc++])){printf"%s ",$ARGV[$argc];} printf"\n"; $tout = $tout_low * (2**$boff); #@temp = join(',',@pkt_th); #print "@temp\n"; #------------------------------------------------------------------------------- while(read(infile,$record,44)){ # read next record #----------------------------------------------------------------------- $tpcount++; # total packets $tstampsec =vec($record,0,32); # timestamp: seconds $tstampusec =vec($record,1,32); # timestamp: microseconds $intf =($tstampusec>>24)&0xff; # get interface number if(($interface ne "") && ($intf != $interface)){next;} # for -i # $tstampusec =$tstampusec&0xffffff; # mask out interface $tstamp =($tstampusec/1e6)+$tstampsec; # composite time stamp if(!$orgtstamp){$orgtstamp=$tstamp;$oldtstamp=$tstamp;} $sa =vec($record,5,32); # IP source address $da =vec($record,6,32); # IP destination address $pl =vec($record,5,16); # packet length $pr =vec($record,17,8); # IP protocol $hl =(vec($record,8,8)&0xf)*2; # header length for 16 bit offsets $sp =vec($record,$hl+4,16); # source port $dp =vec($record,$hl+5,16); # destination ports $fl =vec($record,($hl*2)+8+13,8)&0x3f; # TCP flags if(($pr != 6) & ($pr != 17)){$sp=0;$dp=0;} # unless TCP or UDP set ports=0 if($pr != 6){$fl=0;} # only for TCP #----------------------------------------------------------------------- ###if record exists, update it with new packet's info if(($ap,$ab,$ip,$ib,$at,$al)=split(':',$ta{$sa,$da,$pr,$sp,$dp})){ $ta{$sa,$da,$pr,$sp,$dp}=join(':',++$ap,$ab+$pl,$ip,$ib,$at,$tstamp); ### dynamic timeout algorithm implementation: $life = $tstamp - $at; # Flow classification # First, assign the highest class number. Then move to lower class number whenever it satisfies. for ($i=$boff; ($i >= 0) && ($life <= $tout); $i--) { if ( ($ap == $pkt_th[$i]) && ($life <= $tout_low * (2**$i)) ) { $label{$sa,$da,$pr,$sp,$dp} = $i+1; $dto{$sa,$da,$pr,$sp,$dp} = $tout_low * (2**$i); } } # print "$ta{$sa,$da,$pr,$sp,$dp}\ti=$i, timeout=$dto{$sa,$da,$pr,$sp,$dp}\n"; if($DISPLAY =~ "U"){ $SA=sprintf("%d.%d.%d.%d",($sa>>24)&0xff,($sa>>16)&0xff,($sa>>8)&0xff,$sa&0xff); $DA=sprintf("%d.%d.%d.%d",($da>>24)&0xff,($da>>16)&0xff,($da>>8)&0xff,$da&0xff); printf"U\t%.6f\t%d\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.6f\t%.6f\t%.6f\t%x\n", $tstamp,$tf,$SA,$DA,$pr,$sp,$dp,$ap,$ab+$pl,$ip,$ib,$at,$tstamp,$tstamp-$at,$fl; } } ###else if record exists in the other direction, update it elsif((($ap,$ab,$ip,$ib,$at,$al)=split(':',$ta{$da,$sa,$pr,$dp,$sp})) && $bflag){ $ta{$da,$sa,$pr,$dp,$sp}=join(':',$ap,$ab,++$ip,$ib+$pl,$at,$tstamp); ### dynamic timeout algorithm implementation: $life = $tstamp - $at; # Flow classification # First, assign the highest class number. Then move to lower class number whenever the number of packets exceed higher threshold. for ($i=$boff; ($i >= 0) && ($life <= $tout); $i--) { if ( (($ap+$ip) == $pkt_th[$i]) && ($life <= $tout_low * (2**$i)) ) { $label{$sa,$da,$pr,$sp,$dp} = $i+1; $dto{$sa,$da,$pr,$sp,$dp} = $tout_low * (2**$i); } } if($DISPLAY =~ "U"){ $SA=sprintf("%d.%d.%d.%d",($sa>>24)&0xff,($sa>>16)&0xff,($sa>>8)&0xff,$sa&0xff); $DA=sprintf("%d.%d.%d.%d",($da>>24)&0xff,($da>>16)&0xff,($da>>8)&0xff,$da&0xff); printf"U\t%.6f\t%d\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.6f\t%.6f\t%.6f\t%x\n", $tstamp,$tf,$SA,$DA,$pr,$sp,$dp,$ap,$ab,$ip,$ib+$pl,$at,$tstamp,$tstamp-$at,$fl; } ###else create a new record }else{ $ta{$sa,$da,$pr,$sp,$dp}=join(':',1,$pl,0,0,$tstamp,$tstamp); $label{$sa,$da,$pr,$sp,$dp} = 0; ### initial flow label (meaning not labeled) ### new hash for dynamic timeout $dto{$sa,$da,$pr,$sp,$dp}=$tout; ### $tf++; if($DISPLAY =~ "C"){ $SA=sprintf("%d.%d.%d.%d",($sa>>24)&0xff,($sa>>16)&0xff,($sa>>8)&0xff,$sa&0xff); $DA=sprintf("%d.%d.%d.%d",($da>>24)&0xff,($da>>16)&0xff,($da>>8)&0xff,$da&0xff); printf"C\t%.6f\t%d\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.6f\t%.6f\t%.6f\t%x\n", $tstamp,$tf,$SA,$DA,$pr,$sp,$dp,1,$pl,0,0,$tstamp,$tstamp,0,$fl; } } ###once per second, timeout flows that have expired. if($tstamp >= ($oldtstamp+$tdelta)){ $otf=$tf; foreach $fkey (keys %ta){ ($ap,$ab,$ip,$ib,$at,$al)=split(':',$ta{$fkey}); ### dynamic timeout replaces generic $tout if($al < ($tstamp-$dto{$fkey})){ # timing out transactions ($sa,$da,$pr,$sp,$dp)=split($;,$fkey); ###classification info $class = $label{$sa,$da,$pr,$sp,$dp}; if($DISPLAY =~ "D"){ $SA=sprintf("%d.%d.%d.%d",($sa>>24)&0xff,($sa>>16)&0xff,($sa>>8)&0xff,$sa&0xff); $DA=sprintf("%d.%d.%d.%d",($da>>24)&0xff,($da>>16)&0xff,($da>>8)&0xff,$da&0xff); printf"D\t%.6f\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.6f\t%.6f\t%.6f\t%.6f\t%s\n", $tstamp,$SA,$DA,$pr,$sp,$dp,$ap,$ab,$ip,$ib,$at,$al,$al-$at,$tstamp-$al,$class; } delete $ta{$fkey}; delete $dto{$fkey}; delete $label{$fkey}; $tf--; } } if($DISPLAY =~ "S"){ printf "S\t%.6f\t%d\t%d\t%d\n",$tstamp,$otf,$tf,$otf-$tf; } $oldtstamp=$oldtstamp+$tdelta; if($tstamp >= ($orgtstamp+$etime)){last;} } } # print remaining records if($DISPLAY =~ "X"){ foreach $fkey (keys %ta){ ($ap,$ab,$ip,$ib,$at,$al)=split(':',$ta{$fkey}); ($sa,$da,$pr,$sp,$dp)=split($;,$fkey); ###classify as small medium or large $class = $label{$sa,$da,$pr,$sp,$dp}; $SA=sprintf("%d.%d.%d.%d",($sa>>24)&0xff,($sa>>16)&0xff,($sa>>8)&0xff,$sa&0xff); $DA=sprintf("%d.%d.%d.%d",($da>>24)&0xff,($da>>16)&0xff,($da>>8)&0xff,$da&0xff); printf "X\t%.6f\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.6f\t%.6f\t%.6f\t%.6f\t%s\n", $tstamp,$SA,$DA,$pr,$sp,$dp,$ap,$ab,$ip,$ib,$at,$al,$al-$at,$tstamp-$al,$class; } } sub numerically { $a <=> $b;}