###################################################################################
###################################################################################
#####     Simulace zavislosti zpozdeni na poctu smerovacu a prepinacu         #####      
#####            Jiri Balej, diplomova prace, 21.5.2010                       #####           
###################################################################################
###################################################################################

# vytvoreni instance simulatoru
remove-all-packet-headers;            # odstrani hlavicky paketu
add-packet-header IP TCP;             # prida TCP/IP hlavicky

set ns [new Simulator]

# vytvoreni trasovaciho souboru
set myTRACE [open out.tr w]
$ns trace-all $myTRACE

# vytvoreni souboru pro NAM
set myNAM [open out.nam w]
$ns namtrace-all $myNAM

###################################################################################
#####                      Zakladni nastaveni				      #####
###################################################################################

# pocet routeru v simulaci - ctverec  
set routers 20	
# pocet prepinacu v simulaci - osmiuhlenik 	
set switches 20		

# nastaveni doby zpozdeni smerovacu (v ms)
set routerMin 0.010	
set routerMax 0.100

# nastaveni doby zpozdeni prepinacu (v ms)
set switchMin 0.001	
set switchMax 0.010

# parametry TCP spojeni 
set paket 64		
set ttl 255		

# parametry linek
set bandwidth 10Gb	
set linkdelay 0		

# definice barev
$ns color 1 red
$ns color 2 blue

###################################################################################
###################################################################################

# generatory nahodneho (rovnomerneho) rozlozeni zpozdeni
global defaultRNG
$defaultRNG seed 999

# pro prepinace
 set routerDelay [new RandomVariable/Uniform];
 $routerDelay set min_ $routerMin
 $routerDelay set max_ $routerMax

# pro smerovace
set switchDelay [new RandomVariable/Uniform];
 $switchDelay set min_ $switchMin
 $switchDelay set max_ $switchMax

# definice zdroje
set zdroj [$ns node]

# definice smerovacu (delay box) a linek mezi uzly
for {set i 1} {$i <= $routers} {incr i} {
	set r($i) [$ns DelayBox]
	$r($i) shape box
	if {$i==1} { 
		$ns duplex-link $zdroj $r($i) $bandwidth $linkdelay DropTail
	} else {
		$ns duplex-link $r([expr $i-1]) $r($i) $bandwidth $linkdelay DropTail
	}
}
# definice prepinacu (delay box) a linek mezi uzly
for {set j 1} {$j <= $switches} {incr j} {
	set s($j) [$ns DelayBox]
	$s($j) shape hexagon
	if {$j==1} { 
		$ns duplex-link $r($routers) $s($j) $bandwidth $linkdelay DropTail
	} else {
		$ns duplex-link $s([expr $j-1]) $s($j) $bandwidth $linkdelay DropTail
	}
}

# definice cile
set cil [$ns node]
$ns duplex-link $s($switches) $cil $bandwidth $linkdelay DropTail

# parametry delay boxu (pro smerovace)
for {set i 1} {$i <= $routers} {incr i} {
	$r($i) add-rule [$zdroj id] [$cil id] $routerDelay
	$r($i) set-delay-file "routers.out"
}

# parametry delay boxu (pro prepinace)
for {set j 1} {$j <= $switches} {incr j} {
	$s($j) add-rule [$zdroj id] [$cil id] $switchDelay
	$s($j) set-delay-file "switches.out"
}

# zdroj a cil provozu
set src [new Agent/TCP/FullTcp]
set sink [new Agent/TCP/FullTcp]
$src set packetSize_ $paket
$src set ttl_ $ttl
$src set fid_ 1
$sink set fid_ 1

# pripojeni provozu k uzlum
$ns attach-agent $zdroj $src
$ns attach-agent $cil $sink

# spojeni zdroje s cilem
$ns connect $src $sink
$sink listen

# Definice procedury finish, spousti se vzdy na konci simulace
proc finish {} {
# definovano mimo proceduru (globalni promene)
global ns myTRACE myNAM routers
$ns flush-trace
close $myTRACE
close $myNAM
#AWK kod pro zpracovani zaznamenanych dat
# vytvori dvourozmerne pole dat pro 3D graf
	set awkCode {  
	    {
	    if ($1 == "+" && $12 == "0") {
	# cas odeslani paketu z jednotlivych uzlu ulozen jako pole
	    	cas[$3] = $2;
	    }
	    else if ($1 == "r" && $12 == "0") {
		for (i=0; i<=$3; i++) {
			# vypocet poctu skoku, postupne pro vsechny kombinace delky trasy (0-3,1-3,2-3,3-3...)
			switchhops = 0;
			routerhops = 0;
			if ($3<=r) {
				routerhops = $3-i;
				
			} else {
				if (i<r) {
					switchhops = $3-r;
					routerhops = $3-switchhops-i;
				} else {
					switchhops = $3-i;				
				}
			}
			# ulozeni zpozdeni mezi uzly do dvourozmerneho pole
			if (pocet[routerhops,switchhops] == 0 ) {
				delay[routerhops,switchhops] = $2 - cas[i];
				pocet[routerhops,switchhops] = 1;		
			} else {
			# pricteni doby zpozdeni k jednou zjistene dobe zpozdeni - napr pro 2 routery a 1 smerovac
				delay[routerhops,switchhops] = delay[routerhops,switchhops] + $2 - cas[i];
				pocet[routerhops,switchhops]++;
			}
			# max pocet stanic
			if (sw<$3){
				sw=$3;			
			}
		}
	    }
	}
	END {
		# pocet prepinacu a smerovacu
		routerhops = r;
	        switchhops = sw-r;
		# pro kazdou kombinaci stanic vypocteno zpozdeni a ulozeno do souboru
		for (i=0; i<=switchhops; i++) {
			for (j=0; j<=routerhops; j++) {
				zpozdeni = delay[j,i]/pocet[j,i];
				print j,i,zpozdeni >> "routersSwitches.tr" ;	
				if (i == 0) {
					# pro 2D graf zavislosti na poctu routeru
					zpozdeni = delay[j,i]/pocet[j,i];
					print j, zpozdeni >> "routers.tr" ;
				}		
			}		
		}
	}
    }	
	# pripraveni souboru pro zapis dat
	  exec rm -f routersSwitches.tr routers.tr
  	  exec touch routersSwitches.tr routers.tr

	# spusteni awk skriptu s konstantou poctu smerovacu
  	  exec awk -v "r=$routers" $awkCode out.tr 

	# Otevreni grafu - zakomentovane radky nefunguji dokonale...
	#exec xyz routersSwitches.tr -x_range 0 10 -y_range 0 21 -z_range 0 0.04 
	#exec solidxyz routersSwitches.tr
	#exec contour routersSwitches.tr 
	exec xgraph -x pocet_routeru_(-) -y zpozdeni_(s) routers.tr -geometry 800x400 &
	exec nam out.nam &
	exit 0
}
	# nastaveni casovace
	$ns at 0 "$src advance 1000"
	$ns at 5 "finish"

# spusteni simulace
$ns run
