#!/usr/bin/perl ############################################################### # parseIperfLog.pl # # parses output of the doIper.sh script and creates gnuplot # command files for producing graphics # # Author: Derek Feichtinger 2006-11-12 # # $Id: parseIperfLog.pl,v 1.7 2007/06/01 08:15:04 feichtinger Exp $ ############################################################### use Data::Dumper; use Getopt::Std; use strict; my $outfile_root="pIL"; sub usage { print <<"EOF"; Name: parseIperflog - parse a doIperf.sh generated log file to produce graphics synopsis: parseIperfLog.pl logfile options: -o string : base name for outputfiles -h help The program will store data values in *.out files. Gnuplot command files *.gpl can be used to create the graphics using a commandline like this: gnuplot pILD-140.109.98.111-TO.gpl Author: Derek Feichtinger EOF } ################################################################# # OPTION PARSING my %option=(); getopts("ho:",\%option); if(defined $option{h}) { usage(); exit(0); } if(defined $option{"o"}) { $outfile_root=$option{"o"}; } my $infile=$ARGV[0]; if($infile eq "") { print stderr "Error: missing input file\n\n"; usage(); exit(1); } open(INFILE,"<$infile") or die "Error: Could not open $infile\n"; my %res; my $mode; my $state="p"; # state can be (h)eader, (r)esult or (p)reliminary my $lineno=0; my ($direction,$host,$time,$port,$streams,$tcpwin,$unit,$ID,$sum,$total,$tunit,$rate,$runit); my ($tmp1,$tmp2); while (my $line = ) { $lineno++; if ($line =~ /^command:/) { $state="h"; if ($line =~ /-P\s*(\d+)/) { ($streams) = $line =~ m/-P\s*(\d+)/; } else { $streams=1; } if ($line =~ /-t\s*(\d+)/) { ($time) = $line =~ m/-t\s*(\d+)/; } else { $time=10; # default iperf measuring time } print "$line STREAMS: $streams\n"; $host=$port=$tcpwin=$unit=undef; next; } next if $state eq "p"; if ($state eq "h") { # header if ($line =~ /Server listening on TCP port .*/) { $mode="server"; ($port) = $line =~ m/Server listening on TCP port\s+(\d+)/; print " Server mode, port $port\n"; next; } if ($line =~ /Client connecting to .* TCP port .*/) { $mode="client"; ($host,$port) = $line =~ m/Client connecting to\s+([^,\s]+).*TCP port\s+(\d+)/; print " Client host $host, port $port\n"; $direction=1; next; } if (($tmp1,$tmp2) = $line =~ m/TCP window size:\s+([\d.]+)\s+([^\s]+)/) { ($tcpwin,$unit) = ($tmp1,$tmp2); print " TCP windows size: $tcpwin $unit\n"; next; } if($line =~ /.*local.*connected with.*/) { $state="r"; ($total,$tunit,$rate,$runit)=0; next; } # for iperf version < 2.0 if ($line =~ /\[ ID\]\s+Interval\s+Transfer\s+Bandwidth/) { $state="r"; ($total,$tunit,$rate,$runit)=0; next; } next; } if ($line =~ /\[.*\].*sec\s+[\d.]+\s+[^\s]+\s+[^\s]+\s+[^\s]+/) { ($ID,$total,$tunit,$rate,$runit) = $line =~ m/\[\s*(.*)\].*sec\s+([\d.]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/; if($ID eq "SUM" or $streams == 1) { normalize_rate(\$rate,\$runit) or die "Rate normalization error: stopped at line $lineno\n$line"; normalize_size(\$tcpwin,\$unit) or die "TCPwin normalization error ($tcpwin,$unit): stopped at line $lineno\n$line"; push @{$res{$direction}{$tcpwin}{$streams}},$rate; print " dir: $direction nstreams: $streams Total: $total $tunit Rate: $rate $runit\n"; $direction = -$direction; } next; } #print "### Cannot parse: $line"; } close INFILE; #print Dumper(\%res) . "\n"; # write the gnuplot input and command files foreach $direction (1,-1) { my ($outfile,$gnuplotfile,$dirstr); if ($direction==1) { $dirstr="TO"; } else { $dirstr="FROM"; } $outfile="${outfile_root}-${host}-${dirstr}.out"; $gnuplotfile="${outfile_root}-${host}-${dirstr}.gpl"; my $index=0; my %meanrate; die "Error: $outfile already exists. Cancelling!" if (-e $outfile); open(OUTFILE,">$outfile") or die "Error: Could not open output file $outfile\n"; open(GNUF,">$gnuplotfile") or die "Error: Could not open output file $gnuplotfile\n"; print GNUF <<"EOF"; set title "Throughput $dirstr $host for different TCP window sizes" set output "${outfile_root}-${dirstr}-${host}.png" set term png set xlabel "# of streams" set ylabel "MBits/sec" EOF foreach $tcpwin (sort {$a <=> $b} keys %{$res{$direction}}) { print OUTFILE "# tcp win size $tcpwin KByte\n"; if ($index>0) { print GNUF ",\\\n"; } else { print GNUF "plot " } print GNUF "\"$outfile\" index $index using 1:2 ti \"tcpw $tcpwin KB\""; $index++; foreach $streams (sort {$a <=> $b} keys %{$res{$direction}{$tcpwin}}) { $meanrate{$tcpwin}{$streams}=0; foreach $rate (@{$res{$direction}{$tcpwin}{$streams}}) { print OUTFILE "$streams $rate\n"; $meanrate{$tcpwin}{$streams}+=$rate; } my $nmeas=1+$#{@{$res{$direction}{$tcpwin}{$streams}}}; $meanrate{$tcpwin}{$streams} /= $nmeas; print "meanrate: $meanrate{$tcpwin}{$streams} (#streams=$streams," . "tcpw=$tcpwin, $nmeas measurements)\n"; } print OUTFILE "\n\n"; } print OUTFILE "# Mean rates\n"; foreach $tcpwin (sort {$a <=> $b} keys %{$res{$direction}}) { print OUTFILE "# MEAN tcp win size $tcpwin KByte\n"; print GNUF ",\\\n"; print GNUF "\"$outfile\" index $index using 1:2 ti \"tcpw $tcpwin KB (mean)\" w linespoints"; $index++; foreach $streams (sort {$a <=> $b} keys %{$meanrate{$tcpwin}}) { print OUTFILE "$streams $meanrate{$tcpwin}{$streams}\n"; } print OUTFILE "\n\n"; } print GNUF "\n"; close OUTFILE; close GNUF; } # returns 0 in case of failure sub normalize_rate() { my $value=shift; my $unit=shift; if($$unit eq "Kbits/sec") { $$value=$$value/1000; } elsif ($$unit ne "Mbits/sec") { print STDERR "Error: unknown bandwidth unit: $$unit. Please add to program\n"; return 0; } $$unit="Mbits/sec"; return 1; } # returns 0 in case of failure sub normalize_size() { my $value=shift; my $unit=shift; if($$unit eq "MByte") { $$value*=1000; } elsif ($$unit ne "KByte") { print STDERR "Error: unknown size unit: >$$unit<. Please add to program\n"; return 0; } $$unit="KByte"; return 1; }