#--------------------------------------------------------------------------------
# kred.tcl
# Author: Emmanuel Lochin.
# Dates: Octobre 2006
# Updated: July 2009
#--------------------------------------------------------------------------------

set ns [new Simulator]

set typered [lindex $argv 0]
set debug [lindex $argv 1]

if {$argc < 2} {
     puts stderr "ns kred.tcl \[red|fred|ared|pi|kred\] \[debug 0|1\]" 
     exit 1
}

# RED parameters
#
if {$typered != "pi"} {
	
	Queue/RED set q_weight_ 0.0001
	# maxp = 1 / linterm 
	Queue/RED set linterm_ 10
	Queue/RED set gentle_ true
	# th_min in packets
	Queue/RED set thresh_ 100
	# th_max in packets
	Queue/RED set maxthresh_ 150

	# Queue in packets 
	Queue/RED set queue_in_bytes_ false 
	Queue/RED set summarystats_ true
	Queue/RED set mean_pktsize_ 1000

	Queue/RED set debug_ $debug
	Queue/RED set tdebug_ 0

	Queue/RED/KRED set TrainSteps_ -1
	# Allow to shrink th_min and th_max, computation is as follows:
	#  new_th_min = lambda_low_ * (th_max - th_min)
        #  new_th_max = lambda_high_ * (th_max - th_min)
	Queue/RED/KRED set lambda_high_ 0.0
	Queue/RED/KRED set lambda_low_ 0.0

	# Use the average (0) or the instantaneous (1) queue size value to compute p_max
	Queue/RED/KRED set curqlen_method_ 0
}

set queuesize 200
set Capacity 5Mb
set link 1Mb

switch $typered {
	"ared" {
		Queue/RED set adaptive_ 1
		Queue/RED set feng_adaptive_ 0
		Queue/RED set alpha_ 0.01
		Queue/RED set beta_ 0.9 
		Queue/RED set interval_ 0.5
	}
	"fred" {
	        Queue/RED set adaptive_ 1
	        Queue/RED set feng_adaptive_ 1
		Queue/RED set alpha_ 3.0
		Queue/RED set beta_ 2.0
	}
	"kred" {
		Queue/RED set adaptive_ 0
		Queue/RED set feng_adaptive_ 0
		Queue/RED/KRED set lambda_high_ 0.0
		Queue/RED/KRED set lambda_low_ 0.0
		Queue/RED set interval_ 0.0
	}
	"pi" {
		Queue/PI set bytes_ false
		Queue/PI set queue_in_bytes_ false
		Queue/PI set a_ 0.00001822
		Queue/PI set b_ 0.00001816
		Queue/PI set w_ 170
		Queue/PI set qref_ 100
		Queue/PI set mean_pktsize_ 1000
		Queue/PI set setbit_ false
		Queue/PI set prob_ 0
		Queue/PI set curq_ 0
	}
	"red" {
		Queue/RED set adaptive_ 0
		Queue/RED set feng_adaptive_ 0
	}
	default {
     		puts stderr "ns kred.tcl \[red|fred|ared|kred\] \[debug 0|1\]" 
     		exit 1
	}
}

# Create a nam trace datafile.
# set namfile [open out.nam w]
# $ns namtrace-all $namfile

# Open the trace file
set tracefile1 [open out.tr w]
$ns trace-all $tracefile1
set qf [open stats.que w]

# Set up the network topology shown at the top of this file:
set core [$ns node]
set core2 [$ns node]

# We use RED/KRED for Feng and ARED to get further traces (new methods defined inside kred.cc)
switch $typered {
	"kred" {
		$ns simplex-link $core $core2 $Capacity 30ms RED/KRED
	} 
        "pi" { 
		$ns simplex-link $core $core2 $Capacity 30ms PI
	}
	"red" {
		$ns simplex-link $core $core2 $Capacity 30ms RED
	}
	"ared" {
		$ns simplex-link $core $core2 $Capacity 30ms RED/KRED
	}
	"fred" {
		$ns simplex-link $core $core2 $Capacity 30ms RED/KRED
	}
	default {
     		puts stderr "ns tfrc.tcl \[red|fred|ared|kred\] \[debug 0|1\]" 
     		exit 1
	}
}

$ns simplex-link $core2 $core $Capacity 30ms DropTail

$ns queue-limit $core $core2 $queuesize
$ns queue-limit $core2 $core $queuesize

# Queue stats
set statsq [[$ns link $core $core2] queue]
set traceq [open stats-queue.tr w]
$statsq trace curq_
if {$typered != "pi"} { 
	$statsq trace ave_
}
$statsq attach $traceq

# Create queue monitor for the link
set qmon [$ns monitor-queue $core $core2 $qf]
set samples [new Samples]
$qmon set-delay-samples $samples

# Set up x TCP connection between source and destination following Fig. 3b of the ICC paper

for {set i 1} {$i <= 25} {incr i} {
        set s_($i) [$ns node]
        set r_($i) [$ns node]
	$ns duplex-link $s_($i) $core $link 1ms DropTail
	$ns queue-limit $s_($i) $core $queuesize
	$ns duplex-link $core2 $r_($i) $link 1ms DropTail
        set tcp_($i) [$ns create-connection TCP/Newreno $s_($i) TCPSink $r_($i) 0]
        [set tcp_($i)] set window_ 10000
        $tcp_($i) set fid_ $i
        set ftp_($i) [[set tcp_($i)] attach-app FTP]

	$ns at 0 "[set ftp_($i)] start"
	$ns at 300 "[set ftp_($i)] stop"
}

for {set i 26} {$i <= 50} {incr i} {
        set s_($i) [$ns node]
        set r_($i) [$ns node]
	$ns duplex-link $s_($i) $core $link 1ms DropTail
	$ns queue-limit $s_($i) $core $queuesize
	$ns duplex-link $core2 $r_($i) $link 1ms DropTail
        set tcp_($i) [$ns create-connection TCP/Newreno $s_($i) TCPSink $r_($i) 0]
        [set tcp_($i)] set window_ 10000
        $tcp_($i) set fid_ $i
        set ftp_($i) [[set tcp_($i)] attach-app FTP]

	$ns at 0 "[set ftp_($i)] start"
       	$ns at 50 "[set ftp_($i)] stop"
	$ns at 100 "[set ftp_($i)] start"
       	$ns at 150 "[set ftp_($i)] stop"
	$ns at 150 "[set ftp_($i)] start"
	$ns at 200 "[set ftp_($i)] stop"
	$ns at 250 "[set ftp_($i)] start"
	$ns at 300 "[set ftp_($i)] stop"
}

for {set i 51} {$i <= 100} {incr i} {
        set s_($i) [$ns node]
        set r_($i) [$ns node]
	$ns duplex-link $s_($i) $core $link 1ms DropTail
	$ns queue-limit $s_($i) $core $queuesize
	$ns duplex-link $core2 $r_($i) $link 1ms DropTail
        set tcp_($i) [$ns create-connection TCP/Newreno $s_($i) TCPSink $r_($i) 0]
        [set tcp_($i)] set window_ 10000
        $tcp_($i) set fid_ $i
        set ftp_($i) [[set tcp_($i)] attach-app FTP]

	$ns at 100 "[set ftp_($i)] start"
       	$ns at 150 "[set ftp_($i)] stop"
	$ns at 250 "[set ftp_($i)] start"
	$ns at 300 "[set ftp_($i)] stop"
}



proc finish {} {
   global ns namfile tracefile1 typered traceq samples qf
   $ns flush-trace
   # close $namfile

   # Write stats to file
   # puts $qf "Average queue delay = [$samples mean]"
   # puts $qf "Variance queue delay = [$samples variance]"
   set stdev [expr {sqrt([$samples variance])}]
   # puts $qf "STDEV: $stdev"
   # puts $qf "nb samples = [$samples cnt]"
   puts $qf "[$samples mean] [expr {sqrt([$samples variance])}]"
   
   close $tracefile1
   close $traceq
   set file ${typered}.eps
   if {$typered != "pi"} {
	   exec grep  "a" stats-queue.tr > ave.tr
   }
   exec grep  "Q" stats-queue.tr > cur.tr
   exit 0
}

$ns at 301.0 "finish"
$ns run

