# test-packmime-delaybox.tcl # # Based on .../ns/tcl/ex/rbp_demo.tcl by John Heidemann # # useful constants set CLIENT 0 set SERVER 1 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Usage #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc usage {} { puts stderr {usage: ns test-packmime-delaybox.tcl [variable value] defaults: duration 1 - length of measured simulation (seconds) warmup 0 - warmup interval (seconds) rate 1 - number of new connections / second packmime-count 1 - number of PackMime clouds queue-method DropTail - DropTail, RED, ... queue-length 200 - queue length (packets) link-delay 0ms - propagation delay on network links link-bw 100Mb - bandwidth on network links routers 1 - use routers/delayboxes in network? window 43 - max TCP window size (packets) segsize 1460 - default TCP segment size (bytes) loss-rate 0 - maximum packet loss rate run 1 - experiment run number debug 0 - debug level quiet 1 - don't output status messages? datadir data - directory to store output gzip 1 - gzip trace-queue } exit 1 } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Command-Line Option Default Values #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc default_options {} { global opts opt_wants_arg set raw_opt_info { # # to add a new command-line option, insert the option name and default # value inside this structure # duration 1 warmup 0 # rate -- total number of connections/s # packmime-count -- number of PackMime instances rate 1 packmime-count 1 # network topo queue-method DropTail queue-length 200 link-delay 0ms link-bw 100Mb routers 1 # TCP window 43 segsize 1460 # PackMime vars loss-rate 0 # experiment run number (changing this will change RNG seeds used) run 1 # data collection datadir data quiet 1 debug 0 gzip 1 } # parses the default options and creates the $opts array while {$raw_opt_info != ""} { if {![regexp "^\[^\n\]*\n" $raw_opt_info line]} { break } regsub "^\[^\n\]*\n" $raw_opt_info {} raw_opt_info set line [string trim $line] if {[regexp "^\[ \t\]*#" $line]} { continue } if {$line == ""} { continue } elseif [regexp {^([^ ]+)[ ]+([^ ]+)$} $line dummy key value] { set opts($key) $value set opt_wants_arg($key) 1 } else { set opt_wants_arg($key) 0 # die "unknown stuff in raw_opt_info\n" } } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Process Command Line Arguments #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc process_args {} { global argc argv opts opt_wants_arg default_options for {set i 0} {$i < $argc} {incr i} { set key [lindex $argv $i] if {$key == "-?" || $key == "--help" || $key == "-help" || $key == "-h"} { usage } regsub {^-} $key {} key if {![info exists opt_wants_arg($key)]} { puts stderr "unknown option $key"; usage } if {$opt_wants_arg($key)} { incr i set opts($key) [lindex $argv $i] } else { set opts($key) [expr !opts($key)] } } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Helper function to create duplex links #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc my-duplex-link {ns n1 n2 bw delay queue_method queue_length} { $ns duplex-link $n1 $n2 $bw $delay $queue_method $ns queue-limit $n1 $n2 $queue_length $ns queue-limit $n2 $n1 $queue_length } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # MAIN #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: proc main {} { global argv process_args new MySim } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Instantiate the Class #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Class MySim #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup network links and nodes #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc init_network {} { global opts $self instvar ns_ c_ db_ s_ # Topology # # 100Mb 100Mb 100Mb # client -------- delaybox ------ delaybox ------ server # cloud 0ms 0ms 0ms cloud # # c_(0,packmime-1) db_(0) db_(1) s_(0,packmime-1) # build clients for {set i 0} {$i < $opts(packmime-count)} {incr i} { set c_($i) [$ns_ node] } # build servers for {set i 0} {$i < $opts(packmime-count)} {incr i} { set s_($i) [$ns_ node] } # build delayboxes and links if {$opts(routers) || $opts(packmime-count) > 1} { set db_(0) [$ns_ DelayBox] set db_(1) [$ns_ DelayBox] my-duplex-link $ns_ $db_(0) $db_(1) $opts(link-bw) $opts(link-delay) \ $opts(queue-method) $opts(queue-length) for {set i 0} {$i < $opts(packmime-count)} {incr i} { my-duplex-link $ns_ $c_($i) $db_(0) $opts(link-bw) $opts(link-delay) \ $opts(queue-method) $opts(queue-length) } for {set i 0} {$i < $opts(packmime-count)} {incr i} { my-duplex-link $ns_ $s_($i) $db_(1) $opts(link-bw) $opts(link-delay) \ $opts(queue-method) $opts(queue-length) } } else { my-duplex-link $ns_ $c_(0) $s_(0) $opts(link-bw) $opts(link-delay) \ $opts(queue-method) $opts(queue-length) } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup PackMime Traffic #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc init_connections {} { global opts defaultRNG CLIENT SERVER $self instvar ns_ s_ c_ pm_ db_ rng_ rate_ req_size rsp_size client_delay \ server_delay client_bw server_bw flow_arrive rate_ loss_rate # set rate per PackMime set rate_ [expr [expr $opts(rate) * 1.0] / $opts(packmime-count)] # set TCP options Agent/TCP/FullTcp set segsize_ $opts(segsize) Agent/TCP set window_ $opts(window) # create PackMime(s) and assign clients and server clouds for {set i 0} {$i < $opts(packmime-count)} {incr i} { set pm_($i) [new PackMimeHTTP] $pm_($i) set-client $c_($i) $pm_($i) set-server $s_($i) } # create RNGs (appropriate RNG seeds will be assigned automatically) for {set i 0} {$i < 5} {incr i} { set rng_($i) [new RNG] # advance the seeds for different experiment runs for {set j 1} {$j < $opts(run)} {incr j} { $rng_($i) next-substream } } # create random variables set req_size [new RandomVariable/PackMimeHTTPFileSize $rate_ $CLIENT] set rsp_size [new RandomVariable/PackMimeHTTPFileSize $rate_ $SERVER] set client_delay [new RandomVariable/PackMimeHTTPXmit $rate_ $CLIENT] set server_delay [new RandomVariable/PackMimeHTTPXmit $rate_ $SERVER] set client_bw [new RandomVariable/Constant]; # bw 100 Mbps $client_bw set val_ 100 set server_bw [new RandomVariable/Uniform]; # bw 1-20 Mbps $server_bw set min_ 1 $server_bw set max_ 20 set flow_arrive [new RandomVariable/PackMimeHTTPFlowArrive $rate_] set loss_rate [new RandomVariable/Uniform]; # loss 0-1% $loss_rate set min_ 0 $loss_rate set max_ $opts(loss-rate) # assign RNGs to RandomVariables $req_size use-rng $rng_(0) $rsp_size use-rng $rng_(1) $client_delay use-rng $rng_(2) $server_delay use-rng $rng_(2) $client_bw use-rng $rng_(3) $server_bw use-rng $rng_(3) $flow_arrive use-rng $rng_(4) # setup rules for DelayBoxes for {set i 0} {$i < $opts(packmime-count)} {incr i} { $db_(0) add-rule [$c_($i) id] [$s_($i) id] $client_delay $loss_rate \ $client_bw $db_(0) add-rule [$s_($i) id] [$c_($i) id] $client_delay $loss_rate \ $client_bw } for {set i 0} {$i < $opts(packmime-count)} {incr i} { $db_(1) add-rule [$c_($i) id] [$s_($i) id] $server_delay $loss_rate \ $server_bw $db_(1) add-rule [$s_($i) id] [$c_($i) id] $server_delay $loss_rate \ $server_bw } # set PackMime variables for {set i 0} {$i < $opts(packmime-count)} {incr i} { $pm_($i) set-rate $rate_ $pm_($i) set-req_size $req_size $pm_($i) set-rsp_size $rsp_size $pm_($i) set-flow_arrive $flow_arrive $pm_($i) set-debug $opts(debug) # record HTTP statistics $pm_($i) set-outfile "$opts(datadir)/data-test-packmime-delaybox-$i.dat" } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Schedule Traffic and Packet Tracing #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc schedule_traffic {} { global opts $self instvar ns_ pm_ db_ for {set i 0} {$i < $opts(packmime-count)} {incr i} { $ns_ at 0.0 "$pm_($i) start" } $ns_ at $opts(warmup) "$self trace" } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Setup Tracing #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc trace {} { global opts $self instvar ns_ db_ c_ s_ trace_file_ rate_ Trace set show_tcphdr_ 1 if {$opts(gzip)} { set trace_file_ [open "|gzip > $opts(datadir)/data-test-packmime-delaybox.trq.gz" w] } else { set trace_file_ [open "$opts(datadir)/data-test-packmime-delaybox.trq" w] } if {$opts(routers) || $opts(packmime-count) > 1} { $ns_ trace-queue $db_(0) $db_(1) $trace_file_ $ns_ trace-queue $db_(1) $db_(0) $trace_file_ } else { $ns_ trace-queue $c_(0) $s_(0) $trace_file_ $ns_ trace-queue $s_(0) $c_(0) $trace_file_ } set end [expr $opts(duration) + $opts(warmup)] $ns_ at $end "$ns_ flush-trace ; close $trace_file_ ; $self finish" } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Cleanup #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc finish {} { global opts defaultRNG $self instvar ns_ pm_ db_ rng_ req_size rsp_size client_delay \ server_delay client_bw server_bw flow_arrive loss_rate trace_file_ # stop PackMime for {set i 0} {$i < $opts(packmime-count)} {incr i} { $pm_($i) stop } # delete all of the RNGs and RanVars we created for {set i 0} {$i < 5} {incr i} { delete $rng_($i) } delete $req_size delete $rsp_size delete $client_delay delete $server_delay delete $client_bw delete $server_bw delete $flow_arrive delete $loss_rate # delete PackMime for {set i 0} {$i < $opts(packmime-count)} {incr i} { delete $pm_($i) } # delete DelayBox nodes delete $db_(0) delete $db_(1) # delete Simulator delete $ns_ # post-processing $self process exit 0 } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Post-Process #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc process {} { global opts if {!$opts(quiet)} { puts "Done with simulation, processing..." } if {!$opts(quiet)} { puts stderr "DONE!" } } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Initialize Simulation #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: MySim instproc init {} { global opts $self instvar ns_ exec mkdir -p $opts(datadir) # 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 network and traffic $self init_network $self init_connections $self schedule_traffic # print status if {!$opts(quiet)} { set total [expr $opts(duration) + $opts(warmup)] set minutes [expr $total / 60] puts "run $opts(run)" puts "$opts(rate) connections/s" puts "$opts(packmime-count) PackMime(s)" puts "$minutes minutes (${total} s) warmup $opts(warmup) s" puts "$opts(window) packet window" puts "$opts(loss-rate)% max loss" puts "$opts(link-bw)ps bw" } # start the simulation $ns_ run } main