Commit 48a011cc authored by Leigh B. Stoller's avatar Leigh B. Stoller

Switch from using pathrate for the BW tests, to using locally modifed

version of iperf.
parent 9e62b2e4
......@@ -10,16 +10,17 @@ use Class::Struct;
use POSIX qw(uname);
use IO::Handle;
use English;
use Socket;
#
# Linktest test script. This script is set up to run as root on
# experiment nodes. It is invoked by the Linktest daemon after the
# daemon receives a Linktest "START" event. The script runs tests using
# ping, rude/crude (a real-time packet emitter/collector) and pathrate
# to test all links in the experiment. If the results show a 99% chance
# that the experiment is configured incorrectly, an error is logged to
# the experiment directory in tbdata/linktest. Valid ranges have been
# calibrated ahead of time.
# daemon receives a Linktest "START" event. The script runs tests
# using ping, rude/crude (a real-time packet emitter/collector) and a
# locally hacked iperf to test all links in the experiment. If the
# results show a 99% chance that the experiment is configured
# incorrectly, an error is logged to the experiment directory in
# tbdata/linktest. Valid ranges have been calibrated ahead of time.
#
sub usage()
{
......@@ -31,10 +32,6 @@ sub usage()
}
##############################################################################
# Constants
##############################################################################
......@@ -45,8 +42,7 @@ use constant PATH_NICKNAME => "@CLIENT_VARDIR@/boot/nickname";
use constant PATH_KEYFILE => "@CLIENT_VARDIR@/boot/eventkey";
use constant PATH_RUDE => "/usr/local/bin/rude";
use constant PATH_CRUDE => "/usr/local/bin/crude";
use constant PATH_PATHRATE_SND => "/usr/local/bin/pathrate_snd";
use constant PATH_PATHRATE_RCV => "/usr/local/bin/pathrate_rcv";
use constant PATH_IPERF => "/usr/local/bin/emulab-iperf";
use constant PATH_EMULAB_SYNC => "@CLIENT_BINDIR@/emulab-sync";
use constant PATH_LTEVENT => "@CLIENT_BINDIR@/ltevent";
use constant PATH_TEVC => "@CLIENT_BINDIR@/tevc";
......@@ -56,10 +52,10 @@ use constant EVENTSERVER => "@EVENTSERVER@";
# log files used by tests.
use constant CRUDE_DAT => "/tmp/crude.dat"; # binary data
use constant RUDE_CFG => "/tmp/rude.cfg";
use constant PATHRATE_DAT => "/tmp/pathrate.dat";
use constant IPERF_DAT => "/tmp/iperf.dat";
# pathrate test limits.
use constant LIMIT_BW_HI => 45000000;
# iperf test limits.
use constant LIMIT_BW_HI => 100000000;
use constant LIMIT_BW_LO => 1000000;
use constant LIMIT_BW_LOSS => 0;
......@@ -67,7 +63,8 @@ use constant LIMIT_BW_LOSS => 0;
# Make sure the error is a certain significance before we start reporting it.
use constant INSIGNIFICANT_LAT_ERROR_LO => 0.50; # ms
use constant INSIGNIFICANT_LAT_ERROR_HI => 3.00; # ms
use constant INSIGNIFICANT_BW_ERROR => 1.00; # mb
use constant INSIGNIFICANT_BW_ERROR_HI => 0.01; # percent.
use constant INSIGNIFICANT_BW_ERROR_LO => 0.05; # percent.
# latency must be corrected for xmit delay under this speed.
use constant LAT_LOW_BW => 10000000;
......@@ -112,7 +109,9 @@ use constant EXIT_OK => 0;
# struct for representing a link.
struct ( edge => {
src => '$',
srcip => '$',
dst => '$',
dstip => '$',
bw => '$',
delay => '$',
loss => '$'});
......@@ -300,17 +299,17 @@ if(&is_special_node()) {
# run, if any.
#
&do_unlink(CRUDE_DAT);
&do_unlink(PATHRATE_DAT);
&do_unlink(IPERF_DAT);
&do_unlink(RUDE_CFG);
#
# Start up child processes for receiving RUDE and Pathrate streams.
# Start up child processes for receiving RUDE and iperf streams.
# These run over the lifetime of Linktest to reduce the number of
# barrier synchronizations and startup delays. Always give the
# collectors a moment to start up.
#
if(&dotest(TEST_BW)){
&my_system_initonly(PATH_PATHRATE_SND,"-i","-q");
&my_system_initonly(PATH_IPERF,"-s","-f","b","-u","-w","200000");
sleep(1);
}
if(&dotest(TEST_LOSS)){
......@@ -748,71 +747,124 @@ sub valid_bw {
# Checks bandwidth for directly connected links.
sub bw_test {
my @analyze_list;
my @edge_copy;
@edge_copy = @links;
my @analyze_list = ();
my @edge_copy = @links;
#
# all nodes will execute the same reductions on the edge list
# on their own so that the number of barriers is the same.
while(&has_elems(\@edge_copy)) {
my $edge = &get_assign(\@edge_copy);
#
while (&has_elems(\@edge_copy)) {
my ($edge,$redge) = &get_twoway_assign(\@edge_copy);
if(defined($edge) ) {
if (defined($edge)) {
if($hostname eq $edge->dst) {
#
# iperf does a twoway test.
#
if (&valid_bw($edge)) {
push @analyze_list, $edge;
push(@analyze_list, $edge);
&info(" Starting bandwidth test for " .
&print_link($edge) . "\n");
}
else {
&debug("Skipping bandwidth test for " .
&print_link($edge) . "\n");
&my_system(PATH_PATHRATE_RCV, "-Q","-s",$edge->src,"-q","-N", PATHRATE_DAT);
} else {
&debug("Skipping bandwidth test for " . &print_link($edge) . "\n");
&info("*** Skipping bandwidth test for " .
&print_link($edge) . "\n");
&info("*** Bandwidth is out of range ".
"(" . LIMIT_BW_LO . " <= BW <= " . LIMIT_BW_HI .") ".
"or loss is too high (> " . LIMIT_BW_LOSS . ").\n");
}
if (&valid_bw($redge)) {
push(@analyze_list, $redge);
&info(" Starting bandwidth test for " .
&print_link($redge) . "\n");
}
else {
&debug("Skipping bandwidth test for " .
&print_link($redge) . "\n");
&info("*** Skipping bandwidth test for " .
&print_link($redge) . "\n");
&info("*** Bandwidth is out of range ".
"(" . LIMIT_BW_LO . " <= BW <= " . LIMIT_BW_HI .") ".
"or loss is too high (> " . LIMIT_BW_LOSS . ").\n");
}
# Okay, start the test.
if (&valid_bw($edge) || &valid_bw($redge)) {
&my_system(PATH_IPERF,
"-c", $edge->src, "-t", "10", "-f", "b",
"-r", "-u", "-w", "200000", "-b", "100Mb",
"-x", "s", "-y", "c",
"-L", "4444", "-o", IPERF_DAT);
}
}
}
&barrier();
}
# read the log file.
if(@analyze_list) {
my @results = &read_file(PATHRATE_DAT);
foreach (@results) {
my $edge = shift(@analyze_list);
my $sender = $edge->src;
if(/SNDR=$sender.*CAPL=(\d+\.\d+)Mbps.*CAPH=(\d+\.\d+)Mbps/) {
my $expected = $edge->bw / 1000000;
my $low = $1;
my $hi = $2;
my $diff;
if($expected > $2) {
$diff = $expected - $2;
} elsif ($expected < $1) {
$diff = $1 - $expected;
} else {
$diff = 0;
if (@analyze_list) {
my @results = &read_file(IPERF_DAT);
foreach my $edge (@analyze_list) {
my $found_results = 0;
foreach my $result (@results) {
my @stuff = split(",", $result);
if (scalar(@stuff) < 9) {
die("Error parsing " . IPERF_DAT . "\n");
}
my $output = sprintf "Receive from " . $edge->src
. ": $1/$2/%.1f/%.1f\n", $expected, $diff;
&debug($output);
if($diff > INSIGNIFICANT_BW_ERROR) {
&error (NAME_BW, $edge, "Bandwidth estimate $low to $hi Mbps does not include expected bandwidth $expected Mbps");
my $myip = $stuff[1];
my $port = $stuff[2];
my $hisip = $stuff[3];
my $bw = $stuff[8];
#
# iperf is a twoway test. Both edges represented in the file.
#
if (($hostname eq $edge->dst &&
$edge->dstip eq $myip && "$port" eq "4444" &&
$edge->srcip eq $hisip) ||
($hostname eq $edge->src &&
$edge->dstip eq $myip && "$port" eq "5001" &&
$edge->srcip eq $hisip)) {
my $expected = $edge->bw;
my $diff = abs($bw - $expected);
my $error = undef;
&debug("BW results for " . $edge->src . ": ".
"$bw/$expected/$diff\n");
#
# The measurement tool does not give perfect results.
# However, it reports low all the time, so if it reports
# high, then the link is almost certainly bad.
#
if ($bw > $edge->bw) {
if ($diff > ($expected * INSIGNIFICANT_BW_ERROR_HI)) {
$error = "higher";
}
}
elsif ($bw < $edge->bw) {
if ($diff > ($expected * INSIGNIFICANT_BW_ERROR_LO)) {
$error = "lower";
}
}
if (defined($error)) {
&error(NAME_BW, $edge,
"Bandwidth estimate ($bw bps) is $error ".
"expected ($expected)");
}
$found_results = 1;
last;
}
} else {
die ("Error while parsing " . PATHRATE_DAT . "\n");
}
if (!$found_results) {
&error(NAME_BW, $edge, "Could not find results!");
}
}
}
......@@ -922,7 +974,9 @@ sub get_topo {
} elsif ( /^l (\S+)\s+(\S+)\s+(\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)/) {
my $newEdge = new edge;
$newEdge->src($1);
$newEdge->srcip(hostip($1));
$newEdge->dst($2);
$newEdge->dstip(hostip($2));
$newEdge->bw($3);
$newEdge->delay($4 * 1000); # units of ms
$newEdge->loss($5);
......@@ -1358,3 +1412,10 @@ sub linux_version {
}
return $vers;
}
sub hostip {
my $host = shift(@_);
my (undef,undef,undef,undef,@ipaddrs) = gethostbyname($host);
return inet_ntoa($ipaddrs[0]);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment