#PARAMETERS

#simulation parameters
set simtime 10
puts " "
puts "simulation time = $simtime seconds"
puts " "

#access link parameters
set abw 10Mb
set adel 0.01
set aqsize 1000

#bottleneck link parameters
set bnbw 2500000
set bndel 0.012
set bnqsize 50

#TCP parameters
set maxwnd 50


#TCP/UDP parameters
set mpktsize 1000

#create random number generator
#assigning student number as seed
set student 60854 

set rng [new RNG]
$rng seed $student

#SIMULATOR OBJECT
set nssim [new Simulator]




#TOPOLOGY

#create 4 nodes
set na1 [$nssim node]
set na2 [$nssim node]
set nb1 [$nssim node]
set nb2 [$nssim node]


#create duplex links between nodes
$nssim duplex-link $na1 $nb1 $abw $adel DropTail
$nssim duplex-link $na2 $nb1 $abw $adel DropTail
$nssim duplex-link $nb1 $nb2 $bnbw $bndel DropTail


#set queue sizes
$nssim queue-limit $na1 $nb1 $aqsize
$nssim queue-limit $na2 $nb1 $aqsize
$nssim queue-limit $nb1 $nb2 $bnqsize



#SOURCES AND SINKS

# General parameters for RFC793edu - agent
set initialtimeout 5
set rto 60
set syn true
set jacobsonrtt false
set karnrtt true
set expbackoff true

#The four parameters below need to be changed during the assignment

set exponinc false
set additiveinc false
set slowstart false
set fastrtx false



# create a TCP connection
set tcp1 [$nssim create-connection TCP/RFC793edu $na1 TCPSink $nb2 1]
$tcp1 set fid_ 1

#TCP-RFC793edu parameters
$tcp1 set rtxcur_init_ $initialtimeout
$tcp1 set add793jacobsonrtt_ $jacobsonrtt
$tcp1 set add793karnrtt_ $karnrtt
$tcp1 set add793rto_ $rto
$tcp1 set add793syn_ $syn
$tcp1 set add793expbackoff_ $expbackoff
$tcp1 set add793fastrtx_ $fastrtx
$tcp1 set add793slowstart_ $slowstart
$tcp1 set add793additiveinc_ $additiveinc
$tcp1 set add793exponinc_ $exponinc


# The command below sets the slow start threshold to 1 at the
# beginning of the simulation, uncomment when necessary
 
#$nssim at 0.0 "$tcp1 set ssthresh_ 1"



set ftp1 [new Application/FTP]
$ftp1 attach-agent $tcp1
$tcp1 set packetSize_ $mpktsize
$tcp1 set window_ $maxwnd


#create UDP source
set udp1 [new Agent/UDP]
$nssim attach-agent $na2 $udp1 
set null1 [new Agent/Null]
$nssim attach-agent $nb2 $null1
$nssim connect $udp1 $null1
$udp1 set packetSize_ $mpktsize
$udp1 set fid_ 0

proc sendUDP {} {
    global udp1 mpktsize nssim rng bnbw
    set now [$nssim now]
    $udp1 send $mpktsize
    set exprnd [$rng exponential [expr $mpktsize*8/($bnbw*0.6)]]
#    puts "$exprnd"
    $nssim at [expr $now+$exprnd] "sendUDP"
}

#TRACING AND MONITORING

#set monitoring
set fmon [$nssim makeflowmon Fid]
$nssim attach-fmon [$nssim link $nb1 $nb2] $fmon

proc flowstats {} {
    global fmon
    puts "Packet arrivals and packet drops:"
    set fclassifier [$fmon classifier]
    set flow1 [$fclassifier lookup auto 0 0 1]
    set flow2 [$fclassifier lookup auto 0 0 0]
    set parrtcp [$flow1 set parrivals_]
    set pdropstcp [$flow1 set pdrops_]
    puts "TCP: $parrtcp $pdropstcp"
    set parrudp [$flow2 set parrivals_]
    set pdropsudp [$flow2 set pdrops_]
    puts "UDP: $parrudp $pdropsudp"
    set parr [$fmon set parrivals_]
    set pdrops [$fmon set pdrops_]
    puts "All: $parr $pdrops"
}

#set tracing
set winfile [open win.dat w]


proc record {} {
    global nssim tcp1 winfile maxwnd

    #Sampling interval
    set time 0.01

    #WINDOW FOR TCP1
    #Read congestion window of tcp1
    set curr_cwnd [$tcp1 set cwnd_]
    #Compare the value of cwnd to maxwnd to decide actual sending window
    if { $curr_cwnd < $maxwnd } {
        set curr_wnd $curr_cwnd
    } else {
        set curr_wnd $maxwnd
    }
    #current time
    set now [$nssim now]

    # write the file as window vs time trace
    puts $winfile "$now $curr_wnd"


    #re-schedule procedure
    $nssim at [expr $now+$time] "record"
    }


#RUNNING SIMULATION

#schedule events for ns2
$nssim at 0 "sendUDP"
$nssim at 0 "$ftp1 start"
$nssim at 0 "record"
$nssim at $simtime "flowstats"
$nssim at $simtime "$nssim halt"

#run and end the simulation
$nssim run

#close win.dat
close $winfile

# process window data
exec awk {
    {if ($1 != "") print $1, $2}
} win.dat > winfinal.dat
exec rm win.dat


#Exit
exit 0


