# pm-script.tcl # Based on .../ns/tcl/ex/rbp_demo.tcl by John Heidemann # # Michele C. Weigle, mweigle@cs.odu.edu # Old Dominion University, November 2006 # source proc-args.tcl proc usage {} { puts stderr "usage: ns pm-script.tcl [variable value]" puts stderr { # EXPERIMENT VARS run 1 - run number (substream of RNG) length 3600 - run time (seconds) nPM 1 - number of PM clouds PMrate 1 - new connections per second bw 100 - bottleneck link speed (Mbps) seed 12345 - initial seed for RNG window 64 - max TCP window size (KB) rspsz 50000 - avg rspsz (B) badRNG 0 - poor use of RNG? debug 0 - debug level pairs 0 - target number of completed pairs traceID exp expFile EXPS datadir data } exit 1 } proc default_options {} { global opts set raw_opt_info { # to add a new command-line option, insert the option name and # default value inside this structure run 1 length 3600 nPM 1 PMrate 1 bw 100 seed 12345 window 64 rspsz 50000 badRNG 0 pairs 0 debug 0 traceID exp traceBase exp expFile EXPS datadir data } # parses the default options and creates the $opts array parse_default $raw_opt_info } process_args # setup data directory exec mkdir -p $opts(datadir) if {$opts(run) < 10} { set opts(traceBase) "$opts(datadir)/$opts(traceID)-r0$opts(run)" } else { set opts(traceBase) "$opts(datadir)/$opts(traceID)-r$opts(run)" } dump_opts global defaultRNG if {$opts(seed) > 0} { $defaultRNG seed $opts(seed) for {set j 1} {$j < $opts(run)} {incr j} { $defaultRNG next-substream } } # useful variables set nodes 2 # useful constants set CLIENT 0 set SERVER 1 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup Simulator #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: remove-all-packet-headers; # removes all packet headers add-packet-header IP TCP; # adds TCP/IP headers set ns [new Simulator]; # instantiate the Simulator $ns use-scheduler Heap; # use the Heap scheduler #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup Topology #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # create src nodes for {set i 0} {$i < $nodes} {incr i} { set n_src($i) [$ns node] } # create DelayBox nodes set db(0) [$ns DelayBox] set db(1) [$ns DelayBox] # create sink nodes for {set i 0} {$i < $nodes} {incr i} { set n_sink($i) [$ns node] } # setup links $ns duplex-link $db(0) $db(1) $opts(bw)Mb 23ms DropTail $ns queue-limit $db(1) $db(0) 100 for {set i 0} {$i < $nodes} {incr i} { $ns duplex-link $n_src($i) $db(0) 100Mb 1ms DropTail $ns queue-limit $db(0) $n_src($i) 100 } for {set i 0} {$i < $nodes} {incr i} { $ns duplex-link $n_sink($i) $db(1) 100Mb 1ms DropTail $ns queue-limit $n_sink($i) $db(1) 100 } # setup tracing Trace set show_tcphdr_ 1 set trace_file [open "|gzip > $opts(traceBase).trq.gz" w] for {set i 0} {$i < $nodes} {incr i} { $ns trace-queue $n_src($i) $db(0) $trace_file $ns trace-queue $n_sink($i) $db(1) $trace_file } $ns trace-queue $db(0) $db(1) $trace_file $ns trace-queue $db(1) $db(0) $trace_file # setup TCP Agent/TCP/FullTcp set segsize_ 1460; # set MSS to 1460 bytes Agent/TCP set window_ [expr round ($opts(window) * 1024.0 / 1460.0)] #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup PackMime #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: for {set i 0} {$i < $opts(nPM)} {incr i} { set pm($i) [new PackMimeHTTP] if {$i == 0} { $pm($i) set-client $n_src($i); $pm($i) set-server $n_sink($i); } else { $pm($i) set-client $n_sink($i); $pm($i) set-server $n_src($i); } $pm($i) set-rate $opts(PMrate); # new connections per second $pm($i) set-debug $opts(debug) } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup PackMime Random Variables #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # create RNGs (appropriate RNG seeds are assigned automatically) for {set i 0} {$i < $opts(nPM)} {incr i} { if {!$opts(badRNG)} { set flowRNG($i) [new RNG] set reqsizeRNG($i) [new RNG] set rspsizeRNG($i) [new RNG] set serverdelRNG($i) [new RNG] for {set j 1} {$j < $opts(run)} {incr j} { $flowRNG($i) next-substream $reqsizeRNG($i) next-substream $rspsizeRNG($i) next-substream $serverdelRNG($i) next-substream } } set flow_arrive($i) [new RandomVariable/Exponential] $flow_arrive($i) set avg_ [expr 1.0 / $opts(PMrate)] set req_size($i) [new RandomVariable/Pareto] $req_size($i) set avg_ 50 $req_size($i) set shape_ 1.2 set rsp_size($i) [new RandomVariable/Pareto] $rsp_size($i) set avg_ 7000 $rsp_size($i) set shape_ 1.2 if {!$opts(badRNG)} { set server_del($i) [new RandomVariable/Weibull 0.63 305 $serverdelRNG($i)] } else { set server_del($i) [new RandomVariable/Weibull 0.63 305 $defaultRNG] } if {!$opts(badRNG)} { # assign RNGs to RandomVariables $flow_arrive($i) use-rng $flowRNG($i) $req_size($i) use-rng $reqsizeRNG($i) $rsp_size($i) use-rng $rspsizeRNG($i) } # set PackMime variables $pm($i) set-flow_arrive $flow_arrive($i) $pm($i) set-req_size $req_size($i) $pm($i) set-rsp_size $rsp_size($i) $pm($i) set-server_delay $server_del($i) # record HTTP statistics $pm($i) set-outfile "$opts(traceBase)-PM$i.dat" $pm($i) set-filesz-outfile "$opts(traceBase)-filesz-PM$i.dat" $pm($i) set-samples-outfile "$opts(traceBase)-samples-PM$i.dat" } # # DelayBox # if {! $opts(badRNG)} { set serverDelayRNG [new RNG] set clientDelayRNG [new RNG] for {set i 1} {$i < $opts(run)} {incr i} { $serverDelayRNG next-substream $clientDelayRNG next-substream } } # create random variables set clientDelay [new RandomVariable/PackMimeHTTPXmit $opts(PMrate) $CLIENT] set serverDelay [new RandomVariable/PackMimeHTTPXmit $opts(PMrate) $SERVER] if {!$opts(badRNG)} { $clientDelay use-rng $clientDelayRNG $serverDelay use-rng $serverDelayRNG } # setup rules for DelayBoxes for {set i 0} {$i < $nodes} {incr i} { $db(0) add-rule [$n_src($i) id] [$n_sink($i) id] $clientDelay $db(1) add-rule [$n_src($i) id] [$n_sink($i) id] $serverDelay } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Cleanup #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc finish {} { global ns trace_file $ns flush-trace close $trace_file process exit 0 } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Simulation Schedule #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: for {set i 0} {$i < $opts(nPM)} {incr i} { $ns at 0.0 "$pm($i) start" if {$opts(pairs) == 0} { $ns at $opts(length) "$pm($i) stop" } } if {$opts(pairs) == 0} { $ns at [expr $opts(length) + 1] "finish" } # # GATHER PAIRS # proc gather_pairs {} { global opts pm set pairs 0 for {set i 0} {$i < $opts(nPM)} {incr i} { set pair($i) [$pm($i) get-pairs] set pairs [expr $pairs + $pair($i)] } if {$pairs >= $opts(pairs)} { for {set i 0} {$i < $opts(nPM)} {incr i} { $pm($i) stop } finish } } # # PROCESS # proc process {} { global opts set time [exec date "+%H:%M:%S (%m/%d/%y)"] exec echo " END: $time " >> $opts(datadir)/$opts(expFile) # kbps averaged every 1 s exec zcat $opts(traceBase).trq.gz | awk {{if ($1=="+" && ($3==4 || $3==5)) print $2, ($6*8)/1000.0}} | interval_sum.pl | awk {{print $3}} > $opts(traceBase)-load-1s-fwd.dat # compute running average response size exec awk {{print $3}} $opts(traceBase)-samples-PM0.dat | avg.pl -i > $opts(traceBase)-rspsz-mean-PM0.dat } # stop after $opts(pairs) req/rsp pairs if {$opts(pairs) > 0} { if {[llength $opts(PMrate)] > 1 || [lindex $opts(PMrate) 0] > 0} { for {set i 1} {$i <= $opts(length)} {incr i} { $ns at $i "gather_pairs" } } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Start the Simulation #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: $ns run