diff --git a/pelab/bw-bottleneck/wavelet/Clustering/createClusters.pl b/pelab/bw-bottleneck/createClusters.pl similarity index 55% rename from pelab/bw-bottleneck/wavelet/Clustering/createClusters.pl rename to pelab/bw-bottleneck/createClusters.pl index 9325866b83973dd41a5e33b2dbfc1201809fcc65..2642f8f354bb853b60a112c3e08ebcd79b522bdc 100644 --- a/pelab/bw-bottleneck/wavelet/Clustering/createClusters.pl +++ b/pelab/bw-bottleneck/createClusters.pl @@ -4,51 +4,104 @@ # Copyright (c) 2006 University of Utah and the Flux Group. # All rights reserved. # +use Getopt::Long; +local $RubensteinScriptPath = "/proj/tbres/pramod/bottleneck-emulab/filter/genjitco.i386"; +local $MinSikKimScriptPath = "/proj/tbres/pramod/bottleneck-emulab/devel/MinSikKim/MinSikKimProgram"; +local $ClusterProgramPath = "/proj/tbres/pramod/bottleneck-emulab/devel/Clustering/c++-samples/wvcluster"; +local $elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; -my $expName; -my $projName; -my $logsDir; +local $newExpName = ""; +local $newProjName = ""; +local $logsDir = ""; +local $nodeListFilename = ""; +local $Algorithm = ""; +local $initialConditionsFilename = ""; -my $newExpName; -my $newProjName; +local $scratchSpaceDir = "/tmp/bw-bottleneck/rubenstein"; -%bottleNecks = {}; -my %nodeClasses; -my %nodeNameMap = {}; +# Print usage and die. -die "Usage: perl sharedBottle.pl proj_name exp_name newProj_name newExp_name initial_conditions.txt(Optional)" -if($#ARGV < 3); +sub PrintUsage() +{ + print "Usage: perl createClusters.pl -NewProj=newProjName -NewExp=newExpName -LogDir=/path/to/logs -nodeFile=/path/to/nodeListFile -Algorithm=rubestein/wavelet (rest optional) -RubensteinPath=/path/to/genjitco.arch -MinSikKimPath=/path/to/MinSikKimProgram -ClusterProgPath=/path/to/wvcluster -InitConditions=/path/to/initial_conditions.txt\n"; + exit(1); + +} -$projName = $ARGV[0]; -$expName = $ARGV[1]; -$newProjName = $ARGV[2]; -$newExpName = $ARGV[3]; -$initialConditionsFilename = $ARGV[4]; +# Check for the validity of command line arguments. -$logsDir = "/tmp/testLogs"; +sub processOptions() +{ + &GetOptions("LogDir=s"=>\$logsDir, + "NewProj=s"=>\$newProjName, + "NewExp=s"=>\$newExpName, + "InitConditions=s"=>\$initialConditionsFilename, + "NodeFile=s"=>\$nodeListFilename, + "Algorithm=s"=>\$Algorithm, + "RubensteinPath=s"=>\$RubensteinScriptPath, + "MinSikKimPath=s"=>\$MinSikKimScriptPath, + "ClusterProgPath=s"=>\$ClusterProgramPath); + + if($newExpName eq "" or $newProjName eq "" or $logsDir eq "" or $nodeListFilename eq "" or $Algorithm eq "") + { + print "ERROR: One of the mandatory arguments is empty.\n"; + &PrintUsage(); + } + if(not(-e $logsDir)) + { + print "ERROR: Path provided to the logs directory is invalid.\n"; + &PrintUsage(); + } + + if(not(-e $nodeListFilename)) + { + print "ERROR: Path provided to the file with node names is invalid.\n"; + &PrintUsage(); + + } + + if( not( ($Algorithm =~ /rubenstein/i) || ($Algorithm =~ /wavelet/i) ) ) + { + print "ERROR: Please choose either 'rubenstein' or 'wavelet' ( without quotes, case insensitive ) as the algorithm\n"; + &PrintUsage(); + } + + if($initialConditionsFilename ne "") + { + if(not(-e $initialConditionsFilename)) + { + print "WARNING: The initial conditions file path provided at command line is invalid.\n"; + print "Reverting back to using init-elabnodes.pl\n"; + + } + } +} + + +############################################################################# +############################ MAIN ##################################### +############################################################################# + +# Process the command line options. +&processOptions(); # Get the initial conditions. -$elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; +# Get initial conditions for the paths of interest +# from the database, using init-elabnodes.pl + $initConditionsCommand = $elabInitScript . " -o /tmp/initial-conditions.txt " . $newProjName . " " . $newExpName; -if($#ARGV == 3) +if( ($initialConditionsFilename eq "") or (not(-e $initialConditionsFilename)) ) { system($initConditionsCommand); $initialConditionsFilename = "/tmp/initial-conditions.txt"; } open(CONDITIONS, $initialConditionsFilename); - -my @initialConditions = (); - -while(<CONDITIONS>) -{ - chomp( $_ ); - push(@initialConditions, $_); -} - +my @initialConditions = <CONDITIONS>; +chomp(@initialConditions); close(CONDITIONS); my @addressList = (); @@ -57,16 +110,8 @@ my $addrFlag = 0; my %bwMap = {}; my %delayMap = {}; my %elabMap = {}; - -# Create & send events. -# Get initial conditions for the paths of interest -# from the database, using init-elabnodes.pl -my $tevc = "/usr/testbed/bin/tevc -e $newProjName/$newExpName now"; - -#@@@`/usr/testbed/bin/tevc -w -e $newProjName/$newExpName now elabc reset`; -#@@@`$tevc elabc create start`; - -# Create a list of the IP addresses. +my $numNodes = 0; +# Create a list of the IP addresses listed in the initial-conditions file. foreach $conditionLine (@initialConditions) { if($conditionLine =~ /(\d*?\.\d*?\.\d*?\.(\d*?))\s(\d*?\.\d*?\.\d*?\.\d*?)\s(\d*?)\s(\d*?)\s[\d\w\-\.]*/) @@ -85,9 +130,9 @@ foreach $conditionLine (@initialConditions) if($addrFlag == 0) { push(@addressList, $srcAddress); + $numNodes += 1; $elabMap{$srcAddress} = "elabc-elab-" . $2; - print "Mapping $2 TO $elabMap{$srcAddress}\n"; } # Create a mapping of the initial conditions. @@ -96,6 +141,109 @@ foreach $conditionLine (@initialConditions) } } +# Read the file listing the hostnames of the nodes involved in this +# particular measurement. + +open(INFILE, "<$nodeListFilename"); +my @nodeNameList = <INFILE>; +chomp(@nodeNameList); +close(INFILE); + +# A little checking to ensure that the number of nodes in the NodeList file +# matches the values in the initial conditions file. +if($numNodes != ($#nodeNameList+1) ) +{ + print "ERROR: Mismatch between the number of nodes in InitialConditions.txt and in the NodeList file.\n"; + print "Both the files should have the same number of nodes for a 1-to-1 mapping to be possible.\n"; + exit(1); +} + +# Convert the delay data produced by the wavelet code +# into something palatable to the Rubenstein program. +if($Algorithm =~ /rubenstein/i) +{ + if(-e $scratchSpaceDir) + { + `rm -rf $scratchSpaceDir`; + } + + `mkdir $scratchSpaceDir`; + + opendir(logsDirHandle, $logsDir); + foreach $sourceName (readdir(logsDirHandle)) + { + if( (-d $logsDir . "/" . $sourceName ) and $sourceName ne "." and $sourceName ne ".." ) + { + if( grep(/^$sourceName$/, @nodeNameList) ) + { + @dirNameList = (); + + opendir(sourceDirHandle, $logsDir . "/" . $sourceName); + foreach $destOne (readdir(sourceDirHandle)) + { + if( (-d $logsDir . "/" . $sourceName . "/" . $destOne) && $destOne ne "." && $destOne ne ".." ) + { + if( grep(/^$destOne$/, @nodeNameList) ) + { + if(-e "$logsDir/$sourceName/$destOne/delay.log") + { + push(@dirNameList, $destOne); + } + else + { + print "WARNING: Missing log file $logsDir/$sourceName/$destOne/delay.log\n"; + } + } + } + } + closedir(sourceDirHandle); + + my $firstLevelIndex = 0, $secondLevelIndex = 0; + + foreach $destOne (@dirNameList) + { + $secondLevelIndex = 0; + foreach $destTwo (@dirNameList) + { + if($secondLevelIndex > $firstLevelIndex) + { + `mkdir -p $scratchSpaceDir/$sourceName/$destOne/$destTwo`; + `paste -d ' ' $logsDir/$sourceName/$destOne/delay.log $logsDir/$sourceName/$destTwo/delay.log > $scratchSpaceDir/$sourceName/$destOne/$destTwo/delay.log `; + } + + $secondLevelIndex++; + } + $firstLevelIndex++; + } + } + } + } + + closedir(sourceDirHandle); +# Call our sharedBottle.pl to feed these .filter files we created to +# sharedBottle.pl - It will then create equivalence classes for the +# paths. + + system("perl sharedBottle.pl $scratchSpaceDir $newProjName $newExpName $initialConditionsFilename $RubensteinScriptPath"); + +# Our work here is done, sign off. + exit(0); +} + +############################################################################# +######################### Wavelet processing ################################ +############################################################################# + +%bottleNecks = {}; +my %nodeClasses; +my %nodeNameMap = {}; + +# Create & send events. +my $tevc = "/usr/testbed/bin/tevc -e $newProjName/$newExpName now"; + +`/usr/testbed/bin/tevc -w -e $newProjName/$newExpName now elabc reset`; +`$tevc elabc create start`; + opendir(logsDirHandle, $logsDir); my $addrIndex = 0; @@ -133,8 +281,6 @@ foreach $sourceName (readdir(logsDirHandle)) my @denoisedDelays = (); -# print "Into directory $sourceName\n"; - foreach $destOne (readdir(sourceDirHandle)) { if( (-d $logsDir . "/" . $sourceName . "/" . $destOne) && $destOne ne "." && $destOne ne ".." ) @@ -142,10 +288,8 @@ foreach $sourceName (readdir(logsDirHandle)) # Inside each destination directory, look for # delay.log file with delay values. -# print "Into directory $sourceName/$destOne\n"; - $fullPath = "$logsDir/$sourceName/$destOne/delay.log"; - $waveletScript = "./MinSikKim/MinSikKimProgram $fullPath"; + $waveletScript = "$MinSikKimScriptPath $fullPath"; my @scriptOutput; @scriptOutput = `$waveletScript`; @@ -174,7 +318,7 @@ foreach $sourceName (readdir(logsDirHandle)) # Put this destination in a seperate cluster - we # have zero samples/delay values. - if( ($#scriptOutput == 0) or ($#scriptOutput < 120) ) + if( ($#scriptOutput == 0) or ($#scriptOutput < 128) ) { my @newEquivClass = (); push(@newEquivClass, $i); @@ -234,7 +378,7 @@ foreach $sourceName (readdir(logsDirHandle)) } close(RECORDFILE); - $clusteringProgram = "/tmp/clustering/c++-samples/wvcluster $tmpTreeRecordFile /tmp/tmp.idx"; + $clusteringProgram = "$ClusterProgramPath $tmpTreeRecordFile /tmp/tmp.idx"; my @clusteringOutput ; @@ -298,18 +442,17 @@ foreach $sourceName (readdir(logsDirHandle)) } -# my $delayEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST=" . $addrNodeMapping{$destSeen[$tmpName2]}; my $delayEventCommand = "$tevc ".$elabMap{$addrNodeMapping{$nodeNumberMapping{$tmpName2}}}." modify DEST=" . $addrNodeMapping{$nodeNumberMapping{$tmpName2}}." SRC=".$addrNodeMapping{$sourceName}; $delayEventCommand = $delayEventCommand . " " . "DELAY=" . ($delayMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$nodeNumberMapping{$tmpName2}}}); # Execute the delay event command. print "EXECUTE $delayEventCommand\n"; - #@@@ `$delayEventCommand`; + `$delayEventCommand`; } $bwEventCommand = $bwEventCommand . " " . "BANDWIDTH=" . $maxBw; # Execute the event to set the bandwidth for this equivalence class. print "EXECUTE $bwEventCommand\n"; - #@@@ `$bwEventCommand`; + `$bwEventCommand`; } print "\n\n"; diff --git a/pelab/bw-bottleneck/delay2dump.pl b/pelab/bw-bottleneck/delay2dump.pl index d2ba15eef1355d7e3162a140252e781e2f0a2619..3b76eb12b5fa5244407723d983edca91ba54b7a3 100644 --- a/pelab/bw-bottleneck/delay2dump.pl +++ b/pelab/bw-bottleneck/delay2dump.pl @@ -1,7 +1,7 @@ # delay2dump.pl -if ($ARGV != 2) +if ($#ARGV != 1) { die ("Usage: delay2dump.pl <in-file> <out-path>"); } @@ -16,17 +16,35 @@ $sequence = 0; while ($line = <IN>) { $line =~ /^([0-9.]+) ([0-9.]+) ([0-9.]+) ([0-9.]+)$/; - $send1 = $1; - $send2 = $2; - $delay1 = $3; - $delay2 = $4; + $send1 = $2; + $send2 = $4; + $delay1 = $1; + $delay2 = $3; + + $send1_delay = ($send1 + $delay1)*1000; + $send2_delay = ($send2 + $delay2)*1000; + + $send1 = $send1*1000; + $send2 = $send2*1000; + + $send1_sec = $send1/1000000; + $send1_usec = $send1 % 1000000; + + $send2_sec = $send2/1000000; + $send2_usec = $send2 % 1000000; + + $send1_delay_sec = $send1_delay/1000000; + $send1_delay_usec = $send1_delay % 1000000; + + $send2_delay_sec = $send2_delay/1000000; + $send2_delay_usec = $send2_delay % 1000000; if ($send1 ne -9999 && $send2 ne -9999) { - print (OUT_SOURCE, $send1." 10.0.0.2 ".$sequence); - print (OUT_SOURCE, $send2." 10.0.0.3 ".$sequence); - print (OUT_DEST1, ($send1 + $delay1)." 10.0.0.1 ".$sequence); - print (OUT_DEST2, ($send2 + $delay2)." 10.0.0.1 ".$sequence); + printf (OUT_SOURCE "%d.%d 10.0.0.2 %d\n", $send1_sec,$send1_usec,$sequence); + printf (OUT_SOURCE "%d.%d 10.0.0.3 %d\n", $send2_sec,$send2_usec,$sequence); + printf (OUT_DEST1 "%d.%d 10.0.0.2 %d\n",$send1_delay_sec,$send1_delay_usec,$sequence); + printf (OUT_DEST2 "%d.%d 10.0.0.3 %d\n",$send2_delay_sec,$send2_delay_usec,$sequence); } $sequence++; diff --git a/pelab/bw-bottleneck/dump2filter.pl b/pelab/bw-bottleneck/dump2filter.pl index 6ff2a588f8884830ce4755edaa1c0f33f1deaa01..da52d8cb5493703370ad38ceb5e65c4cfd1595e3 100644 --- a/pelab/bw-bottleneck/dump2filter.pl +++ b/pelab/bw-bottleneck/dump2filter.pl @@ -16,27 +16,27 @@ sub setupDest my %hash; my $file; open($file, "<".$fileName) - or die("Couldn't open file $fileName for reading"); + or die("Couldn't open file $fileName for reading"); my @array = <$file>; for ($i = 0; $i < @array; ++$i) { - $array[$i] =~ /$dumpPattern/; - $hash{$3} = $1; + $array[$i] =~ /$dumpPattern/; + $hash{$3} = $1; } $array[0] =~ /$dumpPattern/; if ($_[0] == 1) { - $dest1Address = $2; + $dest1Address = $2; } else { - $dest2Address = $2; + $dest2Address = $2; } return %hash; } open(SOURCE_IN, "<$basePath/source.dump") - or die("Couldn't open file $basePath/source.dump for reading"); +or die("Couldn't open file $basePath/source.dump for reading"); @source = <SOURCE_IN>; close(SOURCE_IN); @@ -60,32 +60,33 @@ for ($i = 0; $i < @source; ++$i) $flowAddress = $2; $flowSequence = $3; - if ($flowAddress == $dest1Address) + if ($flowAddress eq $dest1Address) { - $destNum = 1; - $destSequence = $sequence1; - ++$sequence1; - $destTime = $dest1{$3}; + $destNum = 1; + $destSequence = $sequence1; + ++$sequence1; + $destTime = $dest1{$3}; } else { - $destNum = 2; - $destSequence = $sequence2; - ++$sequence2; - $destTime = $dest2{$3}; + $destNum = 2; + $destSequence = $sequence2; + ++$sequence2; + $destTime = $dest2{$3}; } if (defined($destTime)) { - if ($flowAddress == $dest1Address) - { - print DEST1_OUT 'Rcvr: (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime.' arr '.$destTime."\n"; - } - else - { - print DEST2_OUT 'Rcvr: (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime.' arr '.$destTime."\n"; - } - print SOURCE_OUT 'Src1: send (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime."\n"; - ++$merged; + if ($flowAddress eq $dest1Address) + { + print DEST1_OUT 'Rcvr: (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime.' arr '.$destTime."\n"; + } + else + { + print DEST2_OUT 'Rcvr: (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime.' arr '.$destTime."\n"; + } + + print SOURCE_OUT 'Src1: send (f'.$destNum.':'.$destSequence.':M'.$merged.')@'.$sourceTime." \n"; + ++$merged; } } diff --git a/pelab/bw-bottleneck/sharedBottle.pl b/pelab/bw-bottleneck/sharedBottle.pl index d6230c3317c50b89a7fdfe9544b232d99268a736..6f508259ae5d263674de0837b9038ac51b1f260a 100644 --- a/pelab/bw-bottleneck/sharedBottle.pl +++ b/pelab/bw-bottleneck/sharedBottle.pl @@ -16,27 +16,27 @@ my $newProjName; %bottleNecks = {}; my %nodeClasses; -die "Usage: perl sharedBottle.pl proj_name exp_name newProj_name newExp_name initial_conditions.txt(Optional)" -if($#ARGV < 3); +die "Usage: perl sharedBottle.pl logsDir newProj_name newExp_name initial_conditions.txt DansScript" +if($#ARGV < 4); -$projName = $ARGV[0]; -$expName = $ARGV[1]; -$newProjName = $ARGV[2]; -$newExpName = $ARGV[3]; -$initialConditionsFilename = $ARGV[4]; +$logsDir = $ARGV[0]; +$newProjName = $ARGV[1]; +$newExpName = $ARGV[2]; +$initialConditionsFilename = $ARGV[3]; +$DansScriptPath = $ARGV[4]; -$logsDir = "/proj/$projName/exp/$expName/logs/dump"; +#$logsDir = "/proj/$projName/exp/$expName/logs/dump"; # Get the initial conditions. -$elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; -$initConditionsCommand = $elabInitScript . " -o /tmp/initial-conditions.txt " . $newProjName . " " . $newExpName; +#$elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; +#$initConditionsCommand = $elabInitScript . " -o /tmp/initial-conditions.txt " . $newProjName . " " . $newExpName; -if($#ARGV == 3) -{ - system($initConditionsCommand); - $initialConditionsFilename = "/tmp/initial-conditions.txt"; -} +#if($#ARGV == 2) +#{ +# system($initConditionsCommand); +# $initialConditionsFilename = "/tmp/initial-conditions.txt"; +#} open(CONDITIONS, $initialConditionsFilename); @@ -111,37 +111,60 @@ foreach $sourceName (readdir(logsDirHandle)) } } + rewinddir(logsDirHandle); # Descend into all the source directories foreach $sourceName (readdir(logsDirHandle)) { - if( (-d $logsDir . "/" . $sourceName ) && $sourceName ne "." && $sourceName ne ".." ) + if( (-d "$logsDir/$sourceName" ) && $sourceName ne "." && $sourceName ne ".." ) { my @destLists; # Then search for all possible destinations for # a particular source. - opendir(sourceDirHandle, $logsDir . "/" . $sourceName); + opendir(sourceDirHandle, "$logsDir/$sourceName"); foreach $destOne (readdir(sourceDirHandle)) { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne) && $destOne ne "." && $destOne ne ".." ) + if( (-d "$logsDir/$sourceName/$destOne") && $destOne ne "." && $destOne ne ".." ) { # Inside each destination directory, look for # all possible second destinations. - opendir(destDirHandle, $logsDir . "/" . $sourceName . "/" . $destOne); + opendir(destDirHandle, "$logsDir/$sourceName/$destOne"); foreach $destTwo (readdir(destDirHandle)) { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne . "/" . $destTwo) && $destTwo ne "." && $destTwo ne ".." ) + if( (-d "$logsDir/$sourceName/$destOne/$destTwo") && $destTwo ne "." && $destTwo ne ".." ) { $fullPath = "$logsDir/$sourceName/$destOne/$destTwo"; # Run Rubenstein's code on the ".filter" files # inside the second destination directory. - `perl /proj/tbres/duerig/testbed/pelab/bw-bottleneck/dump2filter.pl $fullPath`; - $DansScript = "/proj/tbres/duerig/filter/genjitco.FreeBSD"; + + if(-r "$fullPath/delay.log") + { + ($path1Variance, $path2Variance) = &CheckVariance("$fullPath/delay.log"); + + # One of the two paths had low variance - declare this pair of paths as being + # uncorrelated. + if(not( $path1Variance >= 25 and $path2Variance >= 25) ) + { + push(@destLists,$destOne); + push(@destLists,$destTwo); + + printf("WARNING: One or more of paths($sourceName -> $destOne, $sourceName -> $destTwo) have low variance(%.3f,%.3f)\n.Considering these paths as uncorrelated\n", $path1Variance, $path2Variance); + next; + } + } + else + { + print "Missing file(delay.log). Cannot process $fullPath\n"; + next; + } + system("perl delay2dump.pl $fullPath/delay.log $fullPath"); + system("perl dump2filter.pl $fullPath"); + $filterFile1 = $fullPath . "/" . "source.filter"; $filterFile2 = $fullPath . "/" . "dest1.filter"; $filterFile3 = $fullPath . "/" . "dest2.filter"; @@ -149,14 +172,14 @@ foreach $sourceName (readdir(logsDirHandle)) if (!(-r $filterFile1) || !(-r $filterFile2) || !(-r $filterFile3)) { print "Missing file. Cannot process $fullPath\n"; - continue; + next; } - $sharedBottleneckCheck = $DansScript ." ". $filterFile1 - ." ". $filterFile2 ." ". $filterFile3; - + $sharedBottleneckCheck = $DansScriptPath ." ". $filterFile1." ". $filterFile2 ." ". $filterFile3; + print "EXECUTE: $sharedBottleneckCheck\n"; my @scriptOutput = (); @scriptOutput = `$sharedBottleneckCheck | tail -n 2`; +#system("$sharedBottleneckCheck"); # $scriptOutput[0] = "last CHANGE was CORRELATED, corr case: 30203 pkts, test case: 30203 pkts"; # $scriptOutput[1] = "testingabcdef"; @@ -167,9 +190,9 @@ foreach $sourceName (readdir(logsDirHandle)) if($scriptOutput[$#scriptOutput - 1] =~ /last CHANGE\s(\w*)\s(\w*)\,[\w\d\W\:\,]*/) { print "For source $sourceName: Comparing $destOne $destTwo: $scriptOutput[$#scriptOutput]"; - $corrResult = $2; + $corrResult = $2; if($corrResult eq "CORRELATED" - && !($scriptOutput[$#scriptOutput] =~ /nan/)) + && !($scriptOutput[$#scriptOutput] =~ /nan/)) { push(@{ $bottleNecks{$sourceName} },$destOne . ":" . $destTwo); push(@destLists,$destOne); @@ -178,7 +201,7 @@ foreach $sourceName (readdir(logsDirHandle)) } elsif($corrResult eq "UNCORRELATED" - && !($scriptOutput[$#scriptOutput] =~ /nan/)) + && !($scriptOutput[$#scriptOutput] =~ /nan/)) { push(@destLists,$destOne); push(@destLists,$destTwo); @@ -357,10 +380,10 @@ foreach $sourceName (readdir(logsDirHandle)) { if( ($deletionFlagArray[$counter1] != 1) and ($deletionFlagArray[$counter2] != 1) and ($counter1 != $counter2) ) { - $intersectionFlag = &checkIntersection($counter1, $counter2); + $intersectionFlag = &CheckIntersection($counter1, $counter2); if($intersectionFlag) { - &mergeClasses( $counter1, $counter2); + &MergeClasses( $counter1, $counter2); #Mark the equivalence class $counter2 for deletion. $deletionFlagArray[$counter2] = 1; @@ -388,30 +411,48 @@ foreach $sourceName (readdir(logsDirHandle)) # For debugging. - $retVal = &checkSanity(@equivClasses, @adjMatrix); + $retVal = &CheckSanity(@equivClasses, @adjMatrix); if($retVal != 0) { print "WARNING:($sourceName) Transitive property has been violated.\n"; } -# print "(Debugging) Equivalence classes - $sourceName\n"; -#foreach $tmpName (@equivClasses) -# { -# foreach $tmpName2 (@$tmpName) -# { -# print $destSeen[$tmpName2] . " "; -# } -# print "\n"; -# -# } + print "(Debugging) Equivalence classes - $sourceName\n"; +foreach $tmpName (@equivClasses) + { + foreach $tmpName2 (@$tmpName) + { + print $destSeen[$tmpName2] . " "; + } + print "\n"; + + } + +for($i = 0; $i < $numDests; $i++) +{ + my $lonerFlag = 0; + for($j = 0; $j < $numDests; $j++) + { + if($adjMatrix[$i][$j] == 1) + { + $lonerFlag = 1; + last; + } + } - $nodeClasses{$sourceName} = [ @equivClasses ]; + if($lonerFlag == 0) + { + print $destSeen[$i] . "\n"; + } +} + +$nodeClasses{$sourceName} = [ @equivClasses ]; # Send the events to all the nodes which form an equivalent class. - foreach $tmpName (@equivClasses) - { - my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; +foreach $tmpName (@equivClasses) +{ + my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; my $firstDestFlag = 0; my $maxBw = 0; @@ -486,6 +527,7 @@ foreach $sourceName (readdir(logsDirHandle)) } } + print "\n\n"; } closedir(logsDirHandle); @@ -494,7 +536,7 @@ closedir(logsDirHandle); # violated in any equivalence classes - If it has been # correct it (for now) by assuming that all the nodes # have the transitive property wrt shared bottlenecks. -sub checkSanity() +sub CheckSanity() { $retVal = 0; foreach $equivSet (@equivClasses) @@ -519,7 +561,7 @@ sub checkSanity() return $retVal; } -sub checkIntersection() +sub CheckIntersection() { ($index1, $index2) = @_; @array1 = @{ $equivClasses[$index1]}; @@ -538,7 +580,7 @@ sub checkIntersection() return 0; } -sub mergeClasses() +sub MergeClasses() { ($index1, $index2) = @_; @secondArray = @{ $equivClasses[$index2] }; @@ -562,3 +604,54 @@ sub mergeClasses() } } +sub CheckVariance() +{ + open(HANDLE, $_[0]); + + my @delayArray1 = (), @delayArray2 = (); + + while($line = <HANDLE>) + { + if($line =~ /^(\d*)\s(\d*)\s(\d*)\s(\d*)/) + { + push(@delayArray1, $1); + push(@delayArray2, $3); + } + } + close(HANDLE); + + my $delay1Avg = 0, $delay2Avg = 0; + my $delay1Variance = 0, $delay2Variance = 0; + +# Calculate the avg delay for both the paths. + for($i = 0; $i <= $#delayArray1; $i++) + { + $delay1Avg = $delay1Avg + $delayArray1[$i]; + } + $delay1Avg = $delay1Avg/($#delayArray1 + 1); + + for($i = 0; $i <= $#delayArray2; $i++) + { + $delay2Avg = $delay2Avg + $delayArray2[$i]; + } + $delay2Avg = $delay2Avg/($#delayArray2 + 1); + + # Get the variance for each path. + for($i = 0; $i <= $#delayArray1; $i++) + { + $delay1Variance = $delay1Variance + ($delayArray1[$i] - $delay1Avg)*($delayArray1[$i] - $delay1Avg); + } + $delay1Variance = sqrt($delay1Variance); + + for($i = 0; $i <= $#delayArray2; $i++) + { + $delay2Variance = $delay2Variance + ($delayArray2[$i] - $delay2Avg)*($delayArray2[$i] - $delay2Avg); + } + $delay2Variance = sqrt($delay2Variance); + + my @retArray = (); + push(@retArray, $delay1Variance); + push(@retArray, $delay2Variance); + + return @retArray; +} diff --git a/pelab/bw-bottleneck/wavelet/Clustering/udpClient/udpClient.cc b/pelab/bw-bottleneck/wavelet/Clustering/udpClient/udpClient.cc index 24d2f61c701c3830b71acca884ab44aadcd1f4d0..cebedddf36ca866c30c067ed6bb35c83eab19dcc 100644 --- a/pelab/bw-bottleneck/wavelet/Clustering/udpClient/udpClient.cc +++ b/pelab/bw-bottleneck/wavelet/Clustering/udpClient/udpClient.cc @@ -25,7 +25,7 @@ #include <map> #include <sstream> -#define REMOTE_SERVER_PORT 19835 +#define REMOTE_SERVER_PORT 19655 #define MAX_MSG 100 @@ -34,6 +34,7 @@ pcap_t *pcapDescriptor = NULL; using namespace std; +vector< vector<unsigned long long> > sendTimesArray; vector< vector<int> > delaySequenceArray; vector< map<unsigned long long, int> > packetTimeMaps; vector< map<string, unsigned long long> > actualTimeMaps; @@ -70,6 +71,7 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr, ostringstream tmpStrStream; tmpStrStream << origTimestamp; actualTimeMaps[hostIndex][tmpStrStream.str()] = (unsigned long long)(secVal*1000 + usecVal/1000); + sendTimesArray[hostIndex][packetTimeMaps[hostIndex][origTimestamp]] = (unsigned long long)(secVal*1000 + usecVal/1000); printf("Recording Timestamp = %s for Host = %d, value = %llu\n", tmpStrStream.str().c_str(), hostIndex, actualTimeMaps[hostIndex][tmpStrStream.str()]); } else if(packetType == '1') @@ -88,7 +90,9 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr, delaySequenceArray[hostIndex][packetTimeMaps[hostIndex][origTimestamp]] = oneWayDelay; } else + { delaySequenceArray[hostIndex][packetTimeMaps[hostIndex][origTimestamp]] = oneWayDelay - ( actualTimeMaps[hostIndex][tmpStrStream.str()] - origTimestamp); + } cout << " Onewaydelay for the ACK = " << oneWayDelay << " recorded = "<< delaySequenceArray[hostIndex][packetTimeMaps[hostIndex][origTimestamp]] <<", host Index = "<< hostIndex << "\n"; cout <<" Orig timestamp was "<< tmpStrStream.str() << " , actual time = "<< actualTimeMaps[hostIndex][tmpStrStream.str()]<<"\n"; @@ -188,10 +192,15 @@ void pcapCallback(u_char *user, const struct pcap_pkthdr *pcap_info, const u_cha void init_pcap( char *ipAddress) { - char interface[] = "eth1"; + char interface[20] = "vnet"; struct bpf_program bpfProg; char errBuf[PCAP_ERRBUF_SIZE]; char filter[128] = " udp "; + ifstream ifmapHandle; + + ifmapHandle.open("/var/emulab/boot/ifmap", ios::in); + ifmapHandle >> interface; + ifmapHandle.close(); // IP Address and sub net mask. bpf_u_int32 maskp, netp; @@ -200,8 +209,8 @@ void init_pcap( char *ipAddress) pcap_lookupnet(interface, &netp, &maskp, errBuf); pcapDescriptor = pcap_open_live(interface, BUFSIZ, 0, 0, errBuf); localAddress.s_addr = netp; - printf("IP addr = %s\n", ipAddress); - sprintf(filter," udp and ( (src host %s and dst port 19835 ) or (dst host %s and src port 19835 )) ", ipAddress, ipAddress); + printf("IP addr = %s, Interface = %s\n", ipAddress, interface); + sprintf(filter," udp and ( (src host %s and dst port 19655 ) or (dst host %s and src port 19655 )) ", ipAddress, ipAddress); if(pcapDescriptor == NULL) { @@ -229,8 +238,8 @@ int main(int argc, char **argv) string localHostName = argv[3]; int timeout = 2000; // 1 second - int probeRate = 20; // Hz - int probeDuration = 15000; // 15 seconds + int probeRate = 12; // Hz + int probeDuration = 150000; // 150 seconds vector<string> hostList; ifstream inputFileHandle; @@ -299,6 +308,7 @@ int main(int argc, char **argv) fcntl(clientSocket, F_SETFL, flags | O_NONBLOCK); + sendTimesArray.resize(numHosts); delaySequenceArray.resize(numHosts); packetTimeMaps.resize(numHosts); actualTimeMaps.resize(numHosts); @@ -404,10 +414,10 @@ int main(int argc, char **argv) packetTimeMaps[i][sendTime] = packetCounter; delaySequenceArray[i].push_back(-9999); + sendTimesArray[i].push_back(sendTime); cout<< "TO " << hostList[i] << " :Counter=" << packetCounter << " :SendTime= " << sendTime << endl; - } packetCounter++; lastSentTime = getTimeMilli(); @@ -452,6 +462,82 @@ int main(int argc, char **argv) } } + // Find the common sequence of delay indices present for + // all the probed destinations. + int minSequenceLength = 128; + int maxFirstSeenIndex = -999999, minLastSeenIndex = 9999999; + vector<int> delaySequenceSize; + + delaySequenceSize.resize(numHosts); + + for (int i = 0; i < numHosts; i++) + { + int delaySeqLen = delaySequenceArray[i].size(); + int firstSeenIndex = -1; + int lastSeenIndex = -1; + + for (int k = 0; k < delaySeqLen; k++) + { + if (delaySequenceArray[i][k] != -9999) + { + lastSeenIndex = k; + if (firstSeenIndex == -1) + firstSeenIndex = k; + } + } + + if(lastSeenIndex == -1) + { + delaySequenceSize[i] = 0; + } + else + { + delaySequenceSize[i] = lastSeenIndex - firstSeenIndex + 1; + + if(delaySequenceSize[i] >= minSequenceLength) + { + if(lastSeenIndex < minLastSeenIndex) + minLastSeenIndex = lastSeenIndex; + + if(firstSeenIndex > maxFirstSeenIndex) + maxFirstSeenIndex = firstSeenIndex; + } + } + + } + + int delaySeqLen = delaySequenceArray[0].size(); + maxFirstSeenIndex = -1; + minLastSeenIndex = -1; + bool missingSampleFlag = false; + + for (int k = 0; k < delaySeqLen; k++) + { + missingSampleFlag = false; + for (int l = 0; l < numHosts; l++) + { + // Ignore paths which do not have the minimum + // number of delay samples. + if(delaySequenceSize[l] < minSequenceLength) + continue; + + if (delaySequenceArray[l][k] == -9999) + { + missingSampleFlag = true; + } + } + + if(!missingSampleFlag) + { + minLastSeenIndex = k; + if (maxFirstSeenIndex == -1) + maxFirstSeenIndex = k; + } + } + + printf("Maxfirstseenindex = %d, minlastseenIndex = %d\n", maxFirstSeenIndex, minLastSeenIndex); + fflush(stdout); + for (int i = 0; i < numHosts; i++) { string dirPath = outputDirectory + "/" + hostList[i]; @@ -473,6 +559,21 @@ int main(int argc, char **argv) int firstSeenIndex = -1; int lastSeenIndex = -1; + if(delaySequenceSize[i] < minSequenceLength) + { + // Create an empty log file. + ofstream outputFileHandle; + string delayFilePath = dirPath + "/" + "delay.log"; + outputFileHandle.close(); + continue; + } + else + { + firstSeenIndex = maxFirstSeenIndex; + lastSeenIndex = minLastSeenIndex; + } + + /* for (int k = 0; k < delaySeqLen; k++) { if (delaySequenceArray[i][k] != -9999) @@ -482,6 +583,7 @@ int main(int argc, char **argv) firstSeenIndex = k; } } + */ if (lastSeenIndex != -1) { @@ -522,7 +624,7 @@ int main(int argc, char **argv) { for (int k = firstSeenIndex; k < lastSeenIndex + 1; k++) { - outputFileHandle << delaySequenceArray[i][k] << "\n"; + outputFileHandle << delaySequenceArray[i][k] << " "<< sendTimesArray[i][k] << "\n"; } } outputFileHandle.close(); diff --git a/pelab/bw-bottleneck/wavelet/sharedBottle.pl b/pelab/bw-bottleneck/wavelet/sharedBottle.pl deleted file mode 100644 index 47ad749955126489b6be83d8dceac1318469fdf8..0000000000000000000000000000000000000000 --- a/pelab/bw-bottleneck/wavelet/sharedBottle.pl +++ /dev/null @@ -1,490 +0,0 @@ -#!/usr/bin/perl -# -# EMULAB-COPYRIGHT -# Copyright (c) 2006 University of Utah and the Flux Group. -# All rights reserved. -# - - -my $expName; -my $projName; -my $logsDir; - -my $newExpName; -my $newProjName; - -%bottleNecks = {}; -my %nodeClasses; - -die "Usage: perl sharedBottle.pl proj_name exp_name newProj_name newExp_name initial_conditions.txt(Optional)" -if($#ARGV < 3); - -$projName = $ARGV[0]; -$expName = $ARGV[1]; -$newProjName = $ARGV[2]; -$newExpName = $ARGV[3]; -$initialConditionsFilename = $ARGV[4]; - -$logsDir = "/home/pramod/testLogs"; - - -# Get the initial conditions. -$elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; -$initConditionsCommand = $elabInitScript . " -o /tmp/initial-conditions.txt " . $newProjName . " " . $newExpName; - -if($#ARGV == 3) -{ - system($initConditionsCommand); - $initialConditionsFilename = "/tmp/initial-conditions.txt"; -} - -open(CONDITIONS, $initialConditionsFilename); - -my @initialConditions = (); - -while(<CONDITIONS>) -{ - chomp( $_ ); - push(@initialConditions, $_); -} - -close(CONDITIONS); - -my @addressList = (); -my $addrFlag = 0; - -my %bwMap = {}; -my %delayMap = {}; -my %elabMap = {}; - -# Create & send events. -# Get initial conditions for the paths of interest -# from the database, using init-elabnodes.pl -my $tevc = "/usr/testbed/bin/tevc -e $newProjName/$newExpName now"; - -#@@@`/usr/testbed/bin/tevc -w -e $newProjName/$newExpName now elabc reset`; -#@@@`$tevc elabc create start`; - -# Create a list of the IP addresses. -foreach $conditionLine (@initialConditions) -{ - if($conditionLine =~ /(\d*?\.\d*?\.\d*?\.(\d*?))\s(\d*?\.\d*?\.\d*?\.\d*?)\s(\d*?)\s(\d*?)\s[\d\w\-\.]*/) - { - $srcAddress = $1; - $addrFlag = 0; - - foreach $addrEntry (@addressList) - { - if($addrEntry eq $srcAddress) - { - $addrFlag = 1; - } - } - - if($addrFlag == 0) - { - push(@addressList, $srcAddress); - - $elabMap{$srcAddress} = "elabc-elab-" . $2; - print "Mapping $2 TO $elabMap{$srcAddress}\n"; - } - -# Create a mapping of the initial conditions. - $bwMap{$1}{$3} = $4; - $delayMap{$1}{$3} = $5; - } -} - -opendir(logsDirHandle, $logsDir); - -my $addrIndex = 0; -my %addrNodeMapping = {}; - -foreach $sourceName (readdir(logsDirHandle)) -{ -# Map the elab IP address in the initial conditions file, with -# the node names in the gather-results logs directory. - - if( (-d $logsDir . "/" . $sourceName ) && $sourceName ne "." && $sourceName ne ".." ) - { - $addrNodeMapping{$sourceName} = $addressList[$addrIndex]; - print "Second mapping $addressList[$addrIndex] TO $sourceName\n"; - $addrIndex++; - } -} - -rewinddir(logsDirHandle); - -# Descend into all the source directories -foreach $sourceName (readdir(logsDirHandle)) -{ - if( (-d $logsDir . "/" . $sourceName ) && $sourceName ne "." && $sourceName ne ".." ) - { - - my @destLists; -# Then search for all possible destinations for -# a particular source. - opendir(sourceDirHandle, $logsDir . "/" . $sourceName); - - foreach $destOne (readdir(sourceDirHandle)) - { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne) && $destOne ne "." && $destOne ne ".." ) - { - -# Inside each destination directory, look for -# all possible second destinations. - opendir(destDirHandle, $logsDir . "/" . $sourceName . "/" . $destOne); - - foreach $destTwo (readdir(destDirHandle)) - { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne . "/" . $destTwo) && $destTwo ne "." && $destTwo ne ".." ) - { - $fullPath = "$logsDir/$sourceName/$destOne/$destTwo"; -# Run Rubenstein's code on the ".filter" files -# inside the second destination directory. - #`perl /proj/tbres/duerig/testbed/pelab/bw-bottleneck/dump2filter.pl $fullPath`; - #$DansScript = "/proj/tbres/duerig/filter/genjitco.FreeBSD"; - $waveletScript = "/usr/bin/python processDelay.py $fullPath/delay.log"; - #$filterFile1 = $fullPath . "/" . "source.filter"; - #$filterFile2 = $fullPath . "/" . "dest1.filter"; - #$filterFile3 = $fullPath . "/" . "dest2.filter"; - - #if (!(-r $filterFile1) || !(-r $filterFile2) || !($filterFile3)) - #{ - # print "Missing file. Cannot process $fullPath\n"; - # continue; - #} - #$sharedBottleneckCheck = $DansScript ." ". $filterFile1 - # ." ". $filterFile2 ." ". $filterFile3; - - print "RUN: $waveletScript\n"; - my $scriptOutput; - $scriptOutput = `$waveletScript`; - -# $scriptOutput[0] = "last CHANGE was CORRELATED, corr case: 30203 pkts, test case: 30203 pkts"; -# $scriptOutput[1] = "testingabcdef"; - -# "CORRELATED" means that these two nodes have -# a shared bottleneck. - - if($scriptOutput =~ /CORRELATION=(\-?[\d]*\.[\d]*)/) - { - print "For source $sourceName: Comparing $destOne $destTwo: $scriptOutput"; - if($1 > 0.5) - { - push(@{ $bottleNecks{$sourceName} },$destOne . ":" . $destTwo); - push(@destLists,$destOne); - push(@destLists,$destTwo); - print "CORRELATED\n\n"; - - } - elsif($1 < 0.5) - { - push(@destLists,$destOne); - push(@destLists,$destTwo); - print "UNCORRELATED\n\n"; - } - else - { - print "ERROR:($sourceName) Something went wrong in pattern matching phase.\n"; - print "Skipping this source node\n"; - next; - } - } - else - { - print "ERROR:($sourceName) Output line from Rubenstein's code did not match regular expression.\n"; - print "Skipping this source node\n"; - next; - } - } - - } - - closedir(destDirHandle); - } - } - closedir(sourceDirHandle); - -# Make an adjacency matrix. - - my @destSeen = (); - my $flagDestOne = 0; - my $flagDestTwo = 0; - -# Count the number of unique destinations which have measurements -# from this source node. - my $numDests = 0; - my %destHash; - $tmpName = ""; - $destElement = ""; - - foreach $destElement (@destLists) - { - $flagDest = 0; - - foreach $tmpName (@destSeen) - { - if($destElement eq $tmpName) - { - $flagDest = 1; - } - } - - if($flagDest == 0) - { - push(@destSeen,$destElement); - $destHash{$destElement} = $numDests; - $numDests++; - } - } - - local @adjMatrix = (); - print "NUMDESTS = $numDests\n"; - -# Zero out the adjacency matrix. - for($i = 0; $i < $numDests; $i++) - { - for($j = 0; $j < $numDests; $j++) - { - $adjMatrix[$i][$j] = 0; - } - } - - foreach $destPair (@{ $bottleNecks{$sourceName} }) - { - @destNames = split(/:/, $destPair); - - $adjMatrix[$destHash{$destNames[0]}][$destHash{$destNames[1]}] = 1; - $adjMatrix[$destHash{$destNames[1]}][$destHash{$destNames[0]}] = 1; - } - - local @equivClasses = (); - my $numEquivClasses = 0; - - for($i = 0; $i < $numDests; $i++) - { - for($j = 0; $j < $numDests; $j++) - { - if($adjMatrix[$i][$j] == 1) - { - -# Check if any of these destinations is already in an equivalence class. -# If it is, then add the second destination to that class ( do some sanity checking ). - $firstDestFlag = 0; - $secondDestFlag = 0; - $firstDestClassNum = 0; - $secondDestClassNum = 0; - $equivClassNum = 0; - - #print "Testing pair $i $j\n"; - foreach $classArray (@equivClasses) - { - $firstDestFlag = 0; - $secondDestFlag = 0; - - foreach $classDestMember (@{ $classArray } ) - { - # print "Testing against class num - $equivClassNum - $classDestMember\n"; - if($i == $classDestMember ) - { - $firstDestFlag = 1; - $firstDestClassNum = $equivClassNum; - } - if($j == $classDestMember ) - { - $secondDestFlag = 1; - $secondDestClassNum = $equivClassNum; - } - } - - if($firstDestFlag == 1 or $secondDestFlag == 1) - { - last; - } - $equivClassNum++; - } - -# Both these destinations are already in an equivalence class - do nothing. - if($firstDestFlag == 1 && $secondDestFlag == 1) - { - if($firstDestClassNum != $secondDestClassNum) - { - print "ERROR($sourceName): Two destinations sharing a bottleneck link are in different equiv. classes $i $j\n"; - print "Skipping this source node\n"; - } - - } - elsif($firstDestFlag == 1) # Add the second destinaton to the equivalence class. - { - push(@{ $equivClasses[$firstDestClassNum] }, $j); - print "Adding $j to class containing $i\n"; - } - elsif($secondDestFlag == 1) # Add the first destination to the equivalence class. - { - push(@{ $equivClasses[$secondDestClassNum] }, $i); - print "Adding $i to class containing $j\n"; - } - else # Create a new equivalence class, and put these two destinations in it. - { - my @newEquivClass = (); - push(@newEquivClass, $i); - push(@newEquivClass, $j); - - $equivClasses[$numEquivClasses] = [ @newEquivClass ]; - $numEquivClasses++; - - print "Creating new class $i $j\n"; - - } - print "Equivalence classes - $sourceName\n"; - foreach $tmpName (@equivClasses) - { - foreach $tmpName2 (@$tmpName) - { - print $tmpName2 . " "; - } - print "\n"; - - } - } - } - } - - -# After processing all the ".filter" files for each of -# the sources, try to find equivalence classes -# from each source. Check to ensure that the -# transitive property is not being violated. -# For debugging. - - $retVal = &checkSanity(@equivClasses, @adjMatrix); - - if($retVal != 0) - { - print "WARNING:($sourceName) Transitive property has been violated.\n"; - } - print "Equivalence classes after sanityCheck - $sourceName\n"; - foreach $tmpName (@equivClasses) - { - foreach $tmpName2 (@$tmpName) - { - print $tmpName2 . " "; - } - print "\n"; - - } - - #$nodeClasses{$sourceName} = [ @equivClasses ]; - - -# Send the events to all the nodes which form an equivalent class. - foreach $tmpName (@equivClasses) - { - my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; - my $firstDestFlag = 0; - - my $maxBw = 0; - -# Find the maximum available bandwidth in all the paths of this equivalence class. - foreach $tmpName2 (@$tmpName) - { - if($bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}} > $maxBw) - { - $maxBw = $bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}}; - } - } - - foreach $tmpName2 (@$tmpName) - { - if($firstDestFlag == 0) - { - $bwEventCommand = $bwEventCommand . $addrNodeMapping{$destSeen[$tmpName2]}; - $firstDestFlag = 1; - } - else - { - $bwEventCommand = $bwEventCommand . "," . $addrNodeMapping{$destSeen[$tmpName2]}; - } - - -# my $delayEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST=" . $addrNodeMapping{$destSeen[$tmpName2]}; - my $delayEventCommand = "$tevc ".$elabMap{$addrNodeMapping{$destSeen[$tmpName2]}}." modify DEST=" . $addrNodeMapping{$destSeen[$tmpName2]}." SRC=".$addrNodeMapping{$sourceName}; - - $delayEventCommand = $delayEventCommand . " " . "DELAY=" . ($delayMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}}); -# Execute the delay event command. - print "EXECUTE $delayEventCommand\n"; - #@@@ `$delayEventCommand`; - } - $bwEventCommand = $bwEventCommand . " " . "BANDWIDTH=" . $maxBw; -# Execute the event to set the bandwidth for this equivalence class. - print "EXECUTE $bwEventCommand\n"; - #@@@ `$bwEventCommand`; - } - -# Create and send events for all the loner dest nodes reachable from this source node. - for($i = 0; $i < $numDests; $i++) - { - my $lonerFlag = 0; - for($j = 0; $j < $numDests; $j++) - { - if($adjMatrix[$i][$j] == 1) - { - $lonerFlag = 1; - last; - } - } - - if($lonerFlag == 0) - { - my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; - $bwEventCommand = $bwEventCommand . $addrNodeMapping{$destSeen[$i]}; - $bwEventCommand = $bwEventCommand . " BANDWIDTH=".$bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$i]}}; - -# Execute the event to set the bandwidth for this path. - print "EXECUTE: $bwEventCommand\n"; - #@@@ `$bwEventCommand`; - - my $delayEventCommand = "$tevc ".$elabMap{$addrNodeMapping{$destSeen[$i]}}." modify DEST=" . $addrNodeMapping{$destSeen[$i]}." SRC=".$addrNodeMapping{$sourceName}; - - $delayEventCommand = $delayEventCommand . " " . "DELAY=" . ($delayMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$i]}}); - -# Execute the delay event command. - print "EXECUTE: $delayEventCommand\n"; - #@@@ `$delayEventCommand`; - } - } - - } -} - -closedir(logsDirHandle); - -# Check whether the transitive property has been -# violated in any equivalence classes - If it has been -# correct it (for now) by assuming that all the nodes -# have the transitive property wrt shared bottlenecks. -sub checkSanity() -{ - $retVal = 0; - foreach $equivSet (@equivClasses) - { - foreach $classElement ( @$equivSet ) - { - foreach $secondIter (@$equivSet) - { - if($classElement != $secondIter) - { - if($adjMatrix[$classElement][$secondIter] != 1) - { - $adjMatrix[$classElement][$secondIter] = 1; - $retVal = -1; - } - } - } - } - } - - return $retVal; -} - diff --git a/pelab/bw-bottleneck/wavelet/withLibpcap/sharedBottle.pl b/pelab/bw-bottleneck/wavelet/withLibpcap/sharedBottle.pl deleted file mode 100644 index 103d0313df3685cd43b603ebb7518da7e79026bd..0000000000000000000000000000000000000000 --- a/pelab/bw-bottleneck/wavelet/withLibpcap/sharedBottle.pl +++ /dev/null @@ -1,581 +0,0 @@ -#!/usr/bin/perl -# -# EMULAB-COPYRIGHT -# Copyright (c) 2006 University of Utah and the Flux Group. -# All rights reserved. -# - - -my $expName; -my $projName; -my $logsDir; - -my $newExpName; -my $newProjName; - -%bottleNecks = {}; -my %nodeClasses; - -die "Usage: perl sharedBottle.pl proj_name exp_name newProj_name newExp_name initial_conditions.txt(Optional)" -if($#ARGV < 3); - -$projName = $ARGV[0]; -$expName = $ARGV[1]; -$newProjName = $ARGV[2]; -$newExpName = $ARGV[3]; -$initialConditionsFilename = $ARGV[4]; - -$logsDir = "/home/pramod/testLogs6"; - - -# Get the initial conditions. -$elabInitScript = "/proj/tbres/duerig/testbed/pelab/init-elabnodes.pl"; -$initConditionsCommand = $elabInitScript . " -o /tmp/initial-conditions.txt " . $newProjName . " " . $newExpName; - -if($#ARGV == 3) -{ - system($initConditionsCommand); - $initialConditionsFilename = "/tmp/initial-conditions.txt"; -} - -open(CONDITIONS, $initialConditionsFilename); - -my @initialConditions = (); - -while(<CONDITIONS>) -{ - chomp( $_ ); - push(@initialConditions, $_); -} - -close(CONDITIONS); - -my @addressList = (); -my $addrFlag = 0; - -my %bwMap = {}; -my %delayMap = {}; -my %elabMap = {}; - -# Create & send events. -# Get initial conditions for the paths of interest -# from the database, using init-elabnodes.pl -my $tevc = "/usr/testbed/bin/tevc -e $newProjName/$newExpName now"; - -#@@@`/usr/testbed/bin/tevc -w -e $newProjName/$newExpName now elabc reset`; -#@@@`$tevc elabc create start`; - -# Create a list of the IP addresses. -foreach $conditionLine (@initialConditions) -{ - if($conditionLine =~ /(\d*?\.\d*?\.\d*?\.(\d*?))\s(\d*?\.\d*?\.\d*?\.\d*?)\s(\d*?)\s(\d*?)\s[\d\w\-\.]*/) - { - $srcAddress = $1; - $addrFlag = 0; - - foreach $addrEntry (@addressList) - { - if($addrEntry eq $srcAddress) - { - $addrFlag = 1; - } - } - - if($addrFlag == 0) - { - push(@addressList, $srcAddress); - - $elabMap{$srcAddress} = "elabc-elab-" . $2; - print "Mapping $2 TO $elabMap{$srcAddress}\n"; - } - -# Create a mapping of the initial conditions. - $bwMap{$1}{$3} = $4; - $delayMap{$1}{$3} = $5; - } -} - -opendir(logsDirHandle, $logsDir); - -my $addrIndex = 0; -my %addrNodeMapping = {}; - -foreach $sourceName (readdir(logsDirHandle)) -{ -# Map the elab IP address in the initial conditions file, with -# the node names in the gather-results logs directory. - - if( (-d $logsDir . "/" . $sourceName ) && $sourceName ne "." && $sourceName ne ".." ) - { - $addrNodeMapping{$sourceName} = $addressList[$addrIndex]; - print "Second mapping $addressList[$addrIndex] TO $sourceName\n"; - $addrIndex++; - } -} - -rewinddir(logsDirHandle); - -# Descend into all the source directories -foreach $sourceName (readdir(logsDirHandle)) -{ - if( (-d $logsDir . "/" . $sourceName ) && $sourceName ne "." && $sourceName ne ".." ) - { - - my @destLists; -# Then search for all possible destinations for -# a particular source. - opendir(sourceDirHandle, $logsDir . "/" . $sourceName); - - foreach $destOne (readdir(sourceDirHandle)) - { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne) && $destOne ne "." && $destOne ne ".." ) - { - -# Inside each destination directory, look for -# all possible second destinations. - opendir(destDirHandle, $logsDir . "/" . $sourceName . "/" . $destOne); - - foreach $destTwo (readdir(destDirHandle)) - { - if( (-d $logsDir . "/" . $sourceName . "/" . $destOne . "/" . $destTwo) && $destTwo ne "." && $destTwo ne ".." ) - { - $fullPath = "$logsDir/$sourceName/$destOne/$destTwo"; -# Run Rubenstein's code on the ".filter" files -# inside the second destination directory. - #`perl /proj/tbres/duerig/testbed/pelab/bw-bottleneck/dump2filter.pl $fullPath`; - #$DansScript = "/proj/tbres/duerig/filter/genjitco.FreeBSD"; - $waveletScript = "/usr/bin/python processDelay.py $fullPath/delay.log"; - #$filterFile1 = $fullPath . "/" . "source.filter"; - #$filterFile2 = $fullPath . "/" . "dest1.filter"; - #$filterFile3 = $fullPath . "/" . "dest2.filter"; - - #if (!(-r $filterFile1) || !(-r $filterFile2) || !($filterFile3)) - #{ - # print "Missing file. Cannot process $fullPath\n"; - # continue; - #} - #$sharedBottleneckCheck = $DansScript ." ". $filterFile1 - # ." ". $filterFile2 ." ". $filterFile3; - - print "RUN: $waveletScript\n"; - my $scriptOutput; - $scriptOutput = `$waveletScript`; - -# $scriptOutput[0] = "last CHANGE was CORRELATED, corr case: 30203 pkts, test case: 30203 pkts"; -# $scriptOutput[1] = "testingabcdef"; - -# "CORRELATED" means that these two nodes have -# a shared bottleneck. - - if($scriptOutput =~ /CORRELATION=(\-?[\d]*\.[\d]*)/) - { - print "For source $sourceName: Comparing $destOne $destTwo: $scriptOutput"; - if($1 > 0.51) - { - push(@{ $bottleNecks{$sourceName} },$destOne . ":" . $destTwo); - push(@destLists,$destOne); - push(@destLists,$destTwo); - print "CORRELATED\n\n"; - - } - elsif($1 < 0.51) - { - push(@destLists,$destOne); - push(@destLists,$destTwo); - print "UNCORRELATED\n\n"; - } - else - { - print "ERROR:($sourceName) Something went wrong in pattern matching phase.\n"; - print "Skipping this source node\n"; - next; - } - } - else - { - print "ERROR:($sourceName) Output line from Rubenstein's code did not match regular expression.\n"; - print "'$scriptOutput'\n"; - print "Skipping this source node\n"; - next; - } - } - - } - - closedir(destDirHandle); - } - } - closedir(sourceDirHandle); - -# Make an adjacency matrix. - - local @destSeen = (); - my $flagDestOne = 0; - my $flagDestTwo = 0; - -# Count the number of unique destinations which have measurements -# from this source node. - my $numDests = 0; - my %destHash; - $tmpName = ""; - $destElement = ""; - - foreach $destElement (@destLists) - { - $flagDest = 0; - - foreach $tmpName (@destSeen) - { - if($destElement eq $tmpName) - { - $flagDest = 1; - } - } - - if($flagDest == 0) - { - push(@destSeen,$destElement); - $destHash{$destElement} = $numDests; - $numDests++; - } - } - - local @adjMatrix = (); - print "NUMDESTS = $numDests\n"; - -# Zero out the adjacency matrix. - for($i = 0; $i < $numDests; $i++) - { - for($j = 0; $j < $numDests; $j++) - { - $adjMatrix[$i][$j] = 0; - } - } - - foreach $destPair (@{ $bottleNecks{$sourceName} }) - { - @destNames = split(/:/, $destPair); - - $adjMatrix[$destHash{$destNames[0]}][$destHash{$destNames[1]}] = 1; - $adjMatrix[$destHash{$destNames[1]}][$destHash{$destNames[0]}] = 1; - } - - local @equivClasses = (); - my $numEquivClasses = 0; - - for($i = 0; $i < $numDests; $i++) - { - for($j = 0; $j < $numDests; $j++) - { - if($adjMatrix[$i][$j] == 1) - { - -# Check if any of these destinations is already in an equivalence class. -# If it is, then add the second destination to that class ( do some sanity checking ). - $firstDestFlag = 0; - $secondDestFlag = 0; - $firstDestClassNum = 0; - $secondDestClassNum = 0; - $equivClassNum = 0; - - #print "Testing pair $i $j\n"; - foreach $classArray (@equivClasses) - { - $firstDestFlag = 0; - $secondDestFlag = 0; - - foreach $classDestMember (@{ $classArray } ) - { - # print "Testing against class num - $equivClassNum - $classDestMember\n"; - if($i == $classDestMember ) - { - $firstDestFlag = 1; - $firstDestClassNum = $equivClassNum; - } - if($j == $classDestMember ) - { - $secondDestFlag = 1; - $secondDestClassNum = $equivClassNum; - } - } - - if($firstDestFlag == 1 or $secondDestFlag == 1) - { - last; - } - $equivClassNum++; - } - -# Both these destinations are already in an equivalence class - do nothing. - if($firstDestFlag == 1 && $secondDestFlag == 1) - { - if($firstDestClassNum != $secondDestClassNum) - { - print "ERROR($sourceName): Two destinations sharing a bottleneck link are in different equiv. classes $i $j\n"; - print "Skipping this source node\n"; - } - - } - elsif($firstDestFlag == 1) # Add the second destinaton to the equivalence class. - { - push(@{ $equivClasses[$firstDestClassNum] }, $j); - print "Adding $destSeen[$j] to class containing $destSeen[$i]\n"; - } - elsif($secondDestFlag == 1) # Add the first destination to the equivalence class. - { - push(@{ $equivClasses[$secondDestClassNum] }, $i); - print "Adding $destSeen[$i] to class containing $destSeen[$j]\n"; - } - else # Create a new equivalence class, and put these two destinations in it. - { - my @newEquivClass = (); - push(@newEquivClass, $i); - push(@newEquivClass, $j); - - $equivClasses[$numEquivClasses] = [ @newEquivClass ]; - $numEquivClasses++; - - print "Creating new class $destSeen[$i] $destSeen[$j]\n"; - - } - print "Equivalence classes - $sourceName\n"; - foreach $tmpName (@equivClasses) - { - foreach $tmpName2 (@$tmpName) - { - print $destSeen[$tmpName2] . " "; - } - print "\n"; - - } - } - } - } - -############# - $counter1 = 0; - $counter2 = 0; - my @deletionFlagArray = (); - foreach $classVar1 (@equivClasses) - { - push(@deletionFlagArray,0); - } - - foreach $classVar1 (@equivClasses) - { - $counter2 = 0; - $intersectionFlag = 0; - foreach $classVar2 (@equivClasses) - { - if( ($deletionFlagArray[$counter1] != 1) and ($deletionFlagArray[$counter2] != 1) and ($counter1 != $counter2) ) - { - $intersectionFlag = &checkIntersection($counter1, $counter2); - if($intersectionFlag) - { - &mergeClasses( $counter1, $counter2); - - #Mark the equivalence class $counter2 for deletion. - $deletionFlagArray[$counter2] = 1; - } - } - $counter2 += 1; - } - $counter1 += 1; - } - - my @tmpEquivClasses = @equivClasses; - - @equivClasses = (); - - $counter1 = 0; - foreach $classIter (@tmpEquivClasses) - { - if($deletionFlagArray[$counter1] == 0) - { - push(@equivClasses, [@$classIter]); - } - $counter1++; - } - -############ - -# After processing all the ".filter" files for each of -# the sources, try to find equivalence classes -# from each source. Check to ensure that the -# transitive property is not being violated. -# For debugging. - - $retVal = &checkSanity(@equivClasses, @adjMatrix); - - if($retVal != 0) - { - print "WARNING:($sourceName) Transitive property has been violated.\n"; - } - print "Equivalence classes after sanityCheck - $sourceName\n"; - foreach $tmpName (@equivClasses) - { - foreach $tmpName2 (@$tmpName) - { - print $destSeen[$tmpName2] . " "; - } - print "\n"; - - } - - #$nodeClasses{$sourceName} = [ @equivClasses ]; - - -# Send the events to all the nodes which form an equivalent class. - foreach $tmpName (@equivClasses) - { - my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; - my $firstDestFlag = 0; - - my $maxBw = 0; - -# Find the maximum available bandwidth in all the paths of this equivalence class. - foreach $tmpName2 (@$tmpName) - { - if($bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}} > $maxBw) - { - $maxBw = $bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}}; - } - } - - foreach $tmpName2 (@$tmpName) - { - if($firstDestFlag == 0) - { - $bwEventCommand = $bwEventCommand . $addrNodeMapping{$destSeen[$tmpName2]}; - $firstDestFlag = 1; - } - else - { - $bwEventCommand = $bwEventCommand . "," . $addrNodeMapping{$destSeen[$tmpName2]}; - } - - -# my $delayEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST=" . $addrNodeMapping{$destSeen[$tmpName2]}; - my $delayEventCommand = "$tevc ".$elabMap{$addrNodeMapping{$destSeen[$tmpName2]}}." modify DEST=" . $addrNodeMapping{$destSeen[$tmpName2]}." SRC=".$addrNodeMapping{$sourceName}; - - $delayEventCommand = $delayEventCommand . " " . "DELAY=" . ($delayMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$tmpName2]}}); -# Execute the delay event command. - print "EXECUTE $delayEventCommand\n"; - #@@@ `$delayEventCommand`; - } - $bwEventCommand = $bwEventCommand . " " . "BANDWIDTH=" . $maxBw; -# Execute the event to set the bandwidth for this equivalence class. - print "EXECUTE $bwEventCommand\n"; - #@@@ `$bwEventCommand`; - } - -# Create and send events for all the loner dest nodes reachable from this source node. - for($i = 0; $i < $numDests; $i++) - { - my $lonerFlag = 0; - for($j = 0; $j < $numDests; $j++) - { - if($adjMatrix[$i][$j] == 1) - { - $lonerFlag = 1; - last; - } - } - - if($lonerFlag == 0) - { - my $bwEventCommand = "$tevc $elabMap{$addrNodeMapping{$sourceName}} modify DEST="; - $bwEventCommand = $bwEventCommand . $addrNodeMapping{$destSeen[$i]}; - $bwEventCommand = $bwEventCommand . " BANDWIDTH=".$bwMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$i]}}; - -# Execute the event to set the bandwidth for this path. - print "EXECUTE: $bwEventCommand\n"; - #@@@ `$bwEventCommand`; - - my $delayEventCommand = "$tevc ".$elabMap{$addrNodeMapping{$destSeen[$i]}}." modify DEST=" . $addrNodeMapping{$destSeen[$i]}." SRC=".$addrNodeMapping{$sourceName}; - - $delayEventCommand = $delayEventCommand . " " . "DELAY=" . ($delayMap{$addrNodeMapping{$sourceName}}{$addrNodeMapping{$destSeen[$i]}}); - -# Execute the delay event command. - print "EXECUTE: $delayEventCommand\n"; - #@@@ `$delayEventCommand`; - } - } - - } -} - -closedir(logsDirHandle); - -# Check whether the transitive property has been -# violated in any equivalence classes - If it has been -# correct it (for now) by assuming that all the nodes -# have the transitive property wrt shared bottlenecks. -sub checkSanity() -{ - $retVal = 0; - foreach $equivSet (@equivClasses) - { - foreach $classElement ( @$equivSet ) - { - foreach $secondIter (@$equivSet) - { - if($classElement != $secondIter) - { - if($adjMatrix[$classElement][$secondIter] != 1) - { - print "$destSeen[$classElement] $destSeen[$secondIter] violates transitive property\n"; - $adjMatrix[$classElement][$secondIter] = 1; - $retVal = -1; - } - } - } - } - } - - return $retVal; -} - - -sub checkIntersection() -{ - ($index1, $index2) = @_; - @array1 = @{ $equivClasses[$index1]}; - @array2 = @{ $equivClasses[$index2]}; - foreach $arrayMember (@array1) - { - foreach $checkVal (@array2) - { - if($arrayMember == $checkVal) - { - return 1; - } - - } - } - return 0; -} - -sub mergeClasses() -{ - ($index1, $index2) = @_; - @secondArray = @{ $equivClasses[$index2] }; - $intersectionFlag = 0; - - foreach $tmpVal (@secondArray) - { - foreach $arrayMember (@{ $equivClasses[$index1] }) - { - if($arrayMember == $tmpVal) - { - $intersectionFlag = 1; - last; - } - } - - if($intersectionFlag == 0) - { - push(@{ $equivClasses[$index1]}, $tmpVal); - } - } -}