# # {{{EMULAB-LICENSE# # This file is part of the Emulab network testbed software.# # This file is free software: you can redistribute it and/or modify it# under the terms of the GNU Affero General Public License as published by# the Free Software Foundation, either version 3 of the License, or (at# your option) any later version.# # This file is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public# License for more details.# # You should have received a copy of the GNU Affero General Public License# along with this file. If not, see <http://www.gnu.org/licenses/>.# # }}}

OPERATION NUANCES:- If a ping test is scheduled to have a period shorter than the normal latency to the destination, pings will be run sequentially one after the other. There will be no simultaneous tests of the same type to the same destination.

instead of a latency (milliseconds) value. See %ERRID- If a testing process abnormally exits with a value not 0 (say, iperf dies), then the test is rescheduled to be run at a future time. This time is the normal period times the %TEST_FAIL_RETRY ratio. (TODO: add error

reporting here.) CHANGED: 8/3/06 This behavior has changed to the following: - regardless of the return value, parsing the results continues as normal, with the parsing function dealing with setting the error codes in the result.

- If a node/sliver is rebooted, our startup script should run and re-start bgmon. However, the current state of running tests is lost (on purpose!). The management application can query the status using the STATUS command

## XXX / TODO: This is a hack to keep the "outage detection"# stuff working. Outage detection should probably be its own tool.#sub hacky_evalLatencyResult($){my($result)=@_;my%eval_result=(split(/[=,]/,$result));if($eval_result{error}!=0){return-1;}else{return$eval_result{latency};}}

print"rcved ACK, but UDP/tstamp not defined\n"if(!defined$tstamp);print"rcved ACK, but dbfile/tstamp not defined\n"if(!defined$results{tstamp});delLocalDBEntry($index)if($tstampeq$results{tstamp});}elsif($cmdtypeeq"EDIT"){my$linkdest=$sockIn{dstnode};my$testtype=$sockIn{testtype};my$newtestper=$sockIn{testper};my$duration=$sockIn{duration};my$managerID=$sockIn{managerID};

#XXX / TODO: How to handle tool parameterization if an#EDIT comes in with a different toolname, etc..!# -- what are the issues?initTestEv($linkdest,$testtype,$sockIn{toolname},$sockIn{toolwrapperpath},$sockIn{tooltype},$sockIn{req_params},$sockIn{opt_params});

my$destaddr=$runningtestPIDs{$pid}[0];my$testtype=$runningtestPIDs{$pid}[1];my$testev=\%{$testevents{$destaddr}{$testtype}};# handle the case where a test (iperf) times out and bgmon kills itif($testev->{"timedout"}==1){$testev->{"flag_scheduled"}=0;$testev->{"timedout"}=0;

}## XXX should pass each line individually for a continuous# test as it might represent multiple probes. However, we# currently don't have per-line timestamps so the multiple# lines would all have the same timestamp and all but one# will be discarded anyway.#if(@raw_lines){my$raw;foreachmy$line(@raw_lines){

updateTestEvent($testev);print"resetting period from $oldper";print" to ".$testev->{testper}."\n";}if(time_all()<$testev->{"timeOfNextRun"}+$testev->{"testper"}){#if time of next run is in the future, set it to that$testev->{"timeOfNextRun"}+=$testev->{"testper"};}else{

if(($testev->{"timeOfNextRun"}==0)&&($testev->{"managerID"}eq"automanagerclient")&&($testtypeeq"bw")){# init the test based on random initial timemy$range=$testev->{"testper"}-2*$iperfduration;my$random_init=int(rand($range));$testev->{"timeOfNextRun"}=time_all()+$random_init;}else{#if time of next run is in the past, set to current time$testev->{"timeOfNextRun"}=time_all();}

spawnTest($destaddr,$testtype);}}#end loop# may not be needed, but may help detect errorsmy$hangres=detectHang($destaddr);if($hangreseq"bw"){print"HANG: $hangres, $destaddr\n";# reset time of next run$testevents{$destaddr}{bw}{"timeOfNextRun"}=time_all();}

## CALLED FROM A OUTAGETEST RESULTsub updateOutageState_lossCheck($){my($destaddr)=@_;my$latref=\%{$testevents{$destaddr}{latency}};my$outref=\%{$testevents{$destaddr}{outage}};my$curstate=$latref->{outagestate};if($curstateeq"lossCheck"){

if(isWorkingPathDown($testev)<0){# STATE TRANSITION -> normal# Delete outageManID entry in cmdqueue# set period to 0addCmd($testev,Cmd->new($outManID,0,0));$nextstate="normal";$testev->{outStateTime}=0;$testev->{fpingTimeout}=$fpingTimeoutDef;}

if(isWorkingPathDown($testev)<0&&time()-$testev->{outStateTime}>$outTestDur{outageEnd}){# STATE TRANSITION -> normal# Delete outageManID entry in cmdqueue# set period to 0addCmd($testev,Cmd->new($outManID,0,0));$nextstate="normal";$testev->{outStateTime}=0;$testev->{fpingTimeout}=$fpingTimeoutDef;}elsif(isWorkingPathDown($testev)>0){# STATE TRANSITION -> highFreq$nextstate="highFreq";$testev->{outStateTime}=time();$testev->{fpingTimeout}=$outTestFreq{high}*1000/2;}

# See if we should change the continuous statusprint"testper=",$testev->{testper},", limit=",$testev->{limitTime},"\n";if(!$nocontinuous&&$testev->{limitTime}>0&&$testev->{testper}<$CONT_THRESHOLD){$testev->{continuous}=1;}else{undef$testev->{continuous};}