# This is a simple test script to test the *types* of scripts that
# can be generated by my automatic script generator. I wanted to
# write some such scripts by hand first before I unleashed an
# auto script generator on them.
#
# Here, I implemented some extra functionality in ns that enables arbitrary
# node addresses to be specified. This is good for defining traffic that
# constitutes an SLA and it's also good for identifying where traffic comes
# from in these large(r) simulations. It's also good for enabling FECs to 
# be identified in MPLS.
#
# This is a simple test in which I specify a particular set of routes for the
# demands - I want to ensure that the demands are routed properly. Here, the
# traffic engineering is done on a per core node basis rather than a per
# customer demand basis. My intention is to choose different routes for the
# traffic (firstly on a per core node basis) and see how the link loads vary.

Class CoreNetworkData

CoreNetworkData instproc init {} {
    $self instvar itsNumberOfNodes
    $self instvar itsNumberOfLinks
    $self instvar itsCoreNodes
    $self instvar itsCoreLinks

    set itsNumberOfNodes 0
    set itsNumberOfLinks 0
}

#CoreNetworkData instproc SetNumberOfNodes {numberOfNodes} {
#    set itsNumberOfNodes $numberOfNodes
#}

#CoreNetworkData instproc SetNumberOfLinks {numberOfLinks} {
#    set itsNumberOfLinks $numberOfLinks
#}

CoreNetworkData instproc GetCoreNodes {} {
    return itsCoreNodes
}

CoreNetworkData instproc GetCoreLinks {} {
    return itsCoreLinks
}

CoreNetworkData instproc CreateNewNode {nodeAddr} {
    $self instvar itsCoreNodes itsNumberOfNodes
    global ns
    set itsCoreNodes($itsNumberOfNodes) [$ns MPLSnode $nodeAddr]
    
    incr itsNumberOfNodes
}

CoreNetworkData instproc GetNode {nodeID} {
    # here we return the node with the ID in the supplied parameter
    $self instvar itsNumberOfNodes itsCoreNodes

    if {$nodeID >= $itsNumberOfNodes} {
	puts "Cannot find node with id $nodeID"
	exit 1
    }

    return $itsCoreNodes($nodeID)
}

CoreNetworkData instproc CreateNewLink {sourceNodeID destNodeID linkCapacity linkPropDelay} {
    # we currently don't store any info relating to the links in this class
    # it is not clear whether this is a good or a bad strategy - however,
    # since the links are created within this class, we have the ability
    # to add them later.
    global ns
    set sourceNode [$self GetNode $sourceNodeID]
    set destNode [$self GetNode $destNodeID]

    #$ns DSSchedulerLink-duplex-link $sourceNode $destNode \
	\# $linkCapacity $linkPropDelay
    $ns duplex-link $sourceNode $destNode $linkCapacity $linkPropDelay DropTail
}

# this class contains the access network for a particular customer.
Class AccessNetworkData

AccessNetworkData instproc init {} {
    $self instvar itsAccessNodes
    $self instvar itsNumberOfAccessNodes
    $self instvar itsCustomerID

    set itsNumberOfAccessNodes 0
}

AccessNetworkData instproc SetCustomerID {customerID} {
    $self instvar itsCustomerID
    set itsCustomerID $customerID
}

AccessNetworkData instproc CreateAccessNodeAndLink {customerID coreNodeID accessLinkCapacity accessLinkPropDelay coreNetwork} {
    # here we create a new node and a new link
    global ns
    $self instvar itsAccessNodes itsNumberOfAccessNodes

    # this must be changed to obtain the node address
    set coreNode [$coreNetwork GetNode $coreNodeID]
    set coreNodeAddr [$coreNode node-addr]
    set coreNodeAddrDottedQuad [convert-number-to-dotted-quad $coreNodeAddr]

    set ipFields [split "." $coreNodeAddrDottedQuad]

    if {$customerID < 0 || $customerID > 254} {
	puts "$customerID out of range (0-254). Exiting..."
	exit 1
    }

    set nodeAddr "$customerID.0.$itsNumberOfAccessNodes.255"
    # puts "creating new access node with address $nodeAddr"
    set itsAccessNodes($itsNumberOfAccessNodes) [$ns node $nodeAddr]

    #$ns DSSchedulerLink-duplex-link $coreNode \
	\#$itsAccessNodes($itsNumberOfAccessNodes) \
	\# $accessLinkCapacity $accessLinkPropDelay

    $ns duplex-link $coreNode $itsAccessNodes($itsNumberOfAccessNodes) \
	$accessLinkCapacity $accessLinkPropDelay DropTail

    incr itsNumberOfAccessNodes
}

AccessNetworkData instproc GetAccessNode {accessNodeNumber} {
    $self instvar itsAccessNodes
    return $itsAccessNodes($accessNodeNumber)
}

Class CustomerNetworkData

CustomerNetworkData instproc init {} {
    $self instvar itsNodes
}

CustomerNetworkData instproc Initialise {numberOfNodes customerNetworkConnectivity accessNode} {
    global ns
    $self instvar itsNodes

    set accessNodeAddr [$accessNode node-addr]
    set accessNodeAddrDottedQuad [convert-number-to-dotted-quad \
				      $accessNodeAddr]

    set ipFields [split $accessNodeAddrDottedQuad .]
    # puts "access node addr = $accessNodeAddrDottedQuad"
    # puts "ipFields = $ipFields - ipFields(0) = [lindex $ipFields 0]"

    #if {$customerID < 0 || $customerID > 254} {
    # puts "$customerID out of range (0-254). Exiting..."
    # exit 1
    # }

    set rootNodeAddr "[lindex $ipFields 0].[lindex $ipFields 1].[lindex $ipFields 2]"
    
    for {set i 0} {$i < $numberOfNodes} {incr i} {
	set nodeAddr "$rootNodeAddr.$i"
	# puts "creating customer node with addr $nodeAddr"
	set itsNodes($i) [$ns node $nodeAddr]
	# not clear if this should be DS link or not - given the topology,
	# I think it should be. However, I'll run with a non-DS link
	# for the moment.
    }

    # so now I've created the nodes, now I must go on to the links
    set numberOfLinks [llength $customerNetworkConnectivity]
    for {set j 0} {$j < $numberOfLinks} {incr j} {
	set currentLink [lindex $customerNetworkConnectivity $j]
	# puts "currentLink = $currentLink"
	set sourceNodeID [lindex $currentLink 0]
	# puts "sourceNode = $sourceNodeID"
	if {$sourceNodeID == "-1"} {
	    set sourceNode $accessNode
	} else {
	    set sourceNode $itsNodes($sourceNodeID)
	}
	set destNodeID [lindex $currentLink 1]
	# puts "destNode = $destNodeID"
	if {$destNodeID == "-1"} {
	    set destNode $accessNode
	} else {
	    set destNode $itsNodes($destNodeID)
	}
	set linkCapacity [lindex $currentLink 2]
	set linkPropDelay [lindex $currentLink 3]
	set queueType [lindex $currentLink 4]
	$ns duplex-link $sourceNode $destNode $linkCapacity $linkPropDelay \
	    $queueType
    }
}

CustomerNetworkData instproc GetNode {nodeID} {
    # this assumes some number of nodes in the customer network and returns
    # the one indexedby nodeID
    $self instvar itsNodes
    return $itsNodes($nodeID)
}

proc CreateCoreNetwork {numberOfCoreNodes coreLinkData coreNetwork} {
    global ns
    set coreNodes [$coreNetwork GetCoreNodes]
    if {$numberOfCoreNodes > 255} {
	puts "Aaargh - core nodes exceed 255"
	exit 1
    }
    for {set i 0} {$i < $numberOfCoreNodes} {incr i} {
	# there is a problem here if $i exceeds 256 - I don't think it
	# ever should.
	set nodeAddr "32.0.0.$i"
	# puts "creating new core node with addr $nodeAddr"
	$coreNetwork CreateNewNode $nodeAddr
    }


    set numberOfCoreLinks [llength $coreLinkData]
    for {set i 0} {$i < $numberOfCoreLinks} {incr i} {
	set currentLinkData [lindex $coreLinkData $i]
	set sourceNodeID [lindex $currentLinkData 0]
	set destNodeID [lindex $currentLinkData 1]
	set linkCapacity [lindex $currentLinkData 2]
	set linkPropDelay [lindex $currentLinkData 3]
	$coreNetwork CreateNewLink $sourceNodeID $destNodeID \
	    $linkCapacity $linkPropDelay
    }


}

proc CreateAccessNetwork {numberOfCustomers accessLinkData coreNetwork} {

    global accessNetwork numberOfCustomerLocations

    for {set i 0} {$i < $numberOfCustomers} {incr i} {
	# create nodes
	set currentCustomerAccessLinks [lindex $accessLinkData $i]
	set currentNumberOfCustomerLocations \
	    [lindex $numberOfCustomerLocations $i]
	set accessNetwork($i) [new AccessNetworkData]
	for {set j 0} {$j < $currentNumberOfCustomerLocations} {incr j} {
	    set currentAccessLink [lindex $currentCustomerAccessLinks $j]
	    #puts "currentAccessLink = $currentAccessLink"
	    set coreNodeID [lindex $currentAccessLink 0]
	    set accessLinkCapacity [lindex $currentAccessLink 1]
	    set accessLinkPropDelay [lindex $currentAccessLink 2]
	    $accessNetwork($i) CreateAccessNodeAndLink $i $coreNodeID  \
		$accessLinkCapacity $accessLinkPropDelay $coreNetwork
	}
    }
}

proc CreateCustomerNetworks {numberOfCustomers} {
    # here we create all of the customer networks - here the emphasis
    # in on simplicity rather than flexibility: I want to be quickly
    # able to construct a simulation.
    #
    # Here, the customer networks consist of a single source/sink node
    # connected to the router.

    global accessNetwork customerNetworks numberOfCustomerLocations
    global sizeOfCustomerNetworks customerNetworkConnectivity

    for {set i 0} {$i < $numberOfCustomers} {incr i} {
	set currentCustomerAccessNetwork $accessNetwork($i)
	set currentNumberOfCustomerLocations \
	    [lindex $numberOfCustomerLocations $i]
	# puts "current number of customer locations = $currentNumberOfCustomerLocations"
	for {set j 0} {$j < $currentNumberOfCustomerLocations} {incr j} {
	    # puts "i = $i; j = $j"
	    set currentAccessNode \
		[$currentCustomerAccessNetwork GetAccessNode $j]
	    set customerNetworks($i:$j) [new CustomerNetworkData]
	    set numberOfNodes [lindex [lindex $sizeOfCustomerNetworks $i] $j]
	    set thisCustomerNetworkConnectivity \
		[lindex [lindex $customerNetworkConnectivity $i] $j]
	    $customerNetworks($i:$j) Initialise $numberOfNodes \
		$thisCustomerNetworkConnectivity $currentAccessNode
	}
    }
}

proc CreateTopology {numberOfCoreNodes numberOfCustomers coreLinkData accessLinkData coreNetwork} {
    puts "Creating Core Network..."
    CreateCoreNetwork $numberOfCoreNodes $coreLinkData $coreNetwork
    puts "Creating Access Network..."
    CreateAccessNetwork $numberOfCustomers $accessLinkData \
	$coreNetwork
    puts "Creating Customer Networks..."
    CreateCustomerNetworks $numberOfCustomers
}

proc CreateSourceType1 {sourceNodeAddr destNodeAddr params} {
    # source type 1 is a CBR source with parameters rate and packet size

    global ns endTime

    set rate [lindex $params 0]
    set packetSize [lindex $params 1]

    set sourceNode [$ns get-node-by-addr $sourceNodeAddr]
    set destNode [$ns get-node-by-addr $destNodeAddr]

    set sourceAgent [new Agent/UDP]
    $ns attach-agent $sourceNode $sourceAgent
    set destAgent [new Agent/Null]
    $ns attach-agent $destNode $destAgent

    set sourceApp [new Application/Traffic/CBR]
    $sourceApp set rate_ $rate
    $sourceApp set packetSize_ $packetSize

    $sourceApp attach-agent $sourceAgent

    $ns connect $sourceAgent $destAgent

    $ns at 0.1 "$sourceApp start"
    $ns at $endTime "$sourceApp stop"
}

proc CreateSourceType2 {args} {
    puts "Source Type 2 does not exist yet. Exiting..."
    exit 1
}

proc CreateSourceTypeError {sourceType} {
    puts "Error creating source - unknown source Type ($sourceType). Exiting..."
    exit 1
}

proc CreateApplication {sourceNodeAddr destNodeAddr sourceType currentAppData} {
    set appData [lrange $currentAppData 3 end]
    switch $sourceType {
	1 {CreateSourceType1 $sourceNodeAddr $destNodeAddr $appData} 
	2 {CreateSourceType2 $sourceNodeAddr $destNodeAddr $appData}
	default {CreateSourceTypeError $sourceType}
    }
    
    # puts "creating connection between $sourceNodeAddr and $destNodeAddr of type $sourceType"
}

proc CreateSources {} {
    # here we take the source information and create the sources
    # this operates as follows: iterate through all the customers,
    # then through their locations, then through their sources;
    # for each source obtain the source node info, the sink node
    # info, the agent and app type and the parameters of the app and
    # agent

    global numberOfCustomers customerApplicationData \
	numberOfCustomerLocations accessNetwork
    for {set i 0} {$i < $numberOfCustomers} {incr i} {
	set currentNumberOfCustomerLocations \
	    [lindex $numberOfCustomerLocations $i]
	set currentCustomerApplicationData $customerApplicationData($i)
	for {set j 0} {$j < $currentNumberOfCustomerLocations} {incr j} {
	    set accessNodej [$accessNetwork($i) GetAccessNode $j]
	    set accessNodejAddr [$accessNodej node-addr]
	    set accessNodejAddrDQ [convert-number-to-dotted-quad $accessNodejAddr]
	    set ipFields [split $accessNodejAddrDQ .]
	    set accessNodejIdentifier [lindex $ipFields 2]
	    for {set k 0} {$k < $currentNumberOfCustomerLocations} {incr k} {
		set accessNodek [$accessNetwork($i) GetAccessNode $k]
		set accessNodekAddr [$accessNodek node-addr]
		set accessNodekAddrDQ [convert-number-to-dotted-quad $accessNodekAddr]
		set ipFields [split $accessNodekAddrDQ .]
		set accessNodekIdentifier [lindex $ipFields 2]
		# puts "k=$k"
		set currentSources \
		    [lindex [lindex $currentCustomerApplicationData $j] $k]
		set currentNumberOfSources [llength $currentSources]
		for {set l 0} {$l < $currentNumberOfSources} {incr l} {
		    set currentAppData [lindex $currentSources $l]
		    # sourceNodeID is within this network - destNodeID is
		    # within the destination network, which is defined by
		    # k
		    set sourceNodeID [lindex $currentAppData 0]
		    set destNodeID [lindex $currentAppData 1]
		    set sourceType [lindex $currentAppData 2]
		    # puts "connecting from $sourceNodeID to $destNodeID with source type $sourceType"
		    # ok, so now we generate the address of each of the
		    # nodes that we must interconnect - note that this
		    # assumes that the node addressing is as structured
		    # as described above.
		    set sourceNodeAddr "$i.0.$accessNodejIdentifier.$sourceNodeID"
		    set destNodeAddr "$i.0.$accessNodekIdentifier.$destNodeID"
		    CreateApplication $sourceNodeAddr $destNodeAddr $sourceType $currentAppData
		}
	    }
	}
    }
}

proc ConfigureRoutesAndRouters {} {
    global coreNetwork ns customerNetworks routes numberOfCustomers

    set numberOfRoutes [llength $routes]
    set baseLSPID 3000

    for {set i 0} {$i < $numberOfRoutes} {incr i} {
	set currentRoute [lindex $routes $i]
	set nodePair [lindex $currentRoute 0]
	set path [lindex $currentRoute 1]
	set source [lindex $nodePair 0]
	set dest [lindex $nodePair 1]
	set pathLength [llength $path]
	# puts "source = $source, dest = $dest, path = $path"
	set er ""
	for {set j 0} {$j < $pathLength-1} {incr j} {
	    append er "[[$coreNetwork GetNode [lindex $path $j]] node-addr]_"
	}
	set destNodeAddr [[$coreNetwork GetNode [lindex $path end]] node-addr]
	append er "$destNodeAddr"
	# puts "er = $er"
	set srcNode [$coreNetwork GetNode $source]
	set currLSPID [expr $baseLSPID+$i]
	$ns at 0.001 "$srcNode make-explicit-route $destNodeAddr $er $currLSPID -1"
	# now add the customer destination nodes to this LSP
	for {set j 0} {$j < $numberOfCustomers} {incr j} {
	    # here we assume that all of the customer networks contain only
	    # a single node
	    set destAddrToAdd [[$customerNetworks($j:$dest) GetNode 0] node-addr]
	    $ns at 0.01 "$srcNode flow-erlsp-install $destAddrToAdd -1 $currLSPID"
	}
    }
    
    for {set i 0} {$i < 5} {incr i} {
	set currentNode [$coreNetwork GetNode $i]
	$ns at 0.5 "$currentNode pft-dump"
	$ns at 0.5 "$currentNode erb-dump"
	$ns at 0.5 "$currentNode lib-dump"
    }

}

proc CreateQueueMonitors {} {
    global ns numberOfCoreNodes qm coreNetwork

    for {set i 0} {$i < $numberOfCoreNodes} {incr i} {
	for {set j 0} {$j < $numberOfCoreNodes} {incr j} {
	    set source [$coreNetwork GetNode $i]
	    set dest [$coreNetwork GetNode $j]
	    if {[$ns link $source $dest] != "" } {
		set qm($i:$j) [$ns monitor-queue $source $dest ""]
	    }
	}
    }
}

proc DetermineCoreLinkUtilisation {} {
    global ns qm numberOfCoreNodes endTime coreNetwork

    for {set i 0} {$i < $numberOfCoreNodes} {incr i} {
	for {set j 0} {$j < $numberOfCoreNodes} {incr j} {
	    set source [$coreNetwork GetNode $i]
	    set dest [$coreNetwork GetNode $j]
	    if {[$ns link $source $dest] != "" } {
		set usedLinkRate [expr [$qm($i:$j) set bdepartures_]*8/(1000*$endTime)]
		puts "Core Link ($i->$j) - used capacity $usedLinkRate kb/s"
	    }
	}
    }
}

proc finish {} {
    global ns nf qm1
    $ns flush-trace
    close $nf
    DetermineCoreLinkUtilisation
    exit 1
}

proc Run {} {
    # here we just run the damned thing!

    global ns endTime

    $ns at $endTime "finish"
    $ns run
}


set endTime 1.0
set numberOfCoreNodes 5
set coreLinkData [list {0 1 50Mb 0.1ms} \
		      {0 4 50Mb 0.1ms} \
		      {1 2 50Mb 0.1ms} \
		      {1 4 50Mb 0.1ms} \
		      {2 3 50Mb 0.1ms} \
		      {2 4 50Mb 0.1ms} \
		      {3 4 50Mb 0.1ms} \
		     ]
set numberOfCustomers 3
set numberOfCustomerLocations [list 5 5 5]
set sizeOfCustomerNetworks [list \
			    [list 1 1 1 1 1] \
			    [list 1 1 1 1 1] \
			    [list 1 1 1 1 1] ]
set customerNetworkConnectivity [list \
				 [list \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}]] \
				 [list \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}]] \
				 [list \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}] \
				  [list {0 -1 10Mb 0.1ms DropTail}]] \
				 ]
set customerAccessData [list \
			[list \
			 {0 2Mb 1ms} \
			 {1 2Mb 1ms} \
			 {2 2Mb 1ms} \
			 {3 2Mb 1ms} \
			 {4 2Mb 1ms}] \
			[list \
			 {0 2Mb 1ms} \
			 {1 2Mb 1ms} \
			 {2 2Mb 1ms} \
			 {3 2Mb 1ms} \
			 {4 2Mb 1ms}] \
			[list \
			 {0 2Mb 1ms} \
			 {1 2Mb 1ms} \
			 {2 2Mb 1ms} \
			 {3 2Mb 1ms} \
			 {4 2Mb 1ms}]]
# customer applications (include agent stuff)
set customerApplicationData(0) [list \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				   ]
set customerApplicationData(1) [list \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				   ]
set customerApplicationData(2) [list \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				    [list \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					 [list {0 0 1 500kb 500}] \
					] \
				   ]
# routes
# first we set up the routes such that they are only between core nodes - 
# i.e. the traffic engineering is done on a per node basis rather than a
# per customer demand basis.

set routes [list \
		[list {0 1} {0 1}] \
		[list {0 2} {0 1 2}] \
		[list {0 3} {0 4 3}] \
		[list {0 4} {0 4}] \
		[list {1 0} {1 0}] \
		[list {1 2} {1 2}] \
		[list {1 3} {1 2 3}] \
		[list {1 4} {1 4}] \
		[list {2 0} {2 1 0}] \
		[list {2 1} {2 1}] \
		[list {2 3} {2 3}] \
		[list {2 4} {2 4}] \
		[list {3 0} {3 4 0}] \
		[list {3 1} {3 4 1}] \
		[list {3 2} {3 2}] \
		[list {3 4} {3 4}] \
		[list {4 0} {4 0}] \
		[list {4 1} {4 1}] \
		[list {4 2} {4 2}] \
		[list {4 3} {4 3}] ]

set ns [new Simulator]

set nf [open test1.nam w]
$ns namtrace-all $nf

set coreNetwork [new CoreNetworkData]
CreateTopology $numberOfCoreNodes $numberOfCustomers $coreLinkData \
    $customerAccessData $coreNetwork
$ns configure-ldp-on-all-mpls-nodes
$ns enable-control-driven
#for {set i 0} {$i < $numberOfNodes} {incr i} {
#    set currentNode [$coreNetwork GetNode $i]
#    puts "node $i: control_driven_trigger = [$currentNode set control_driven_trigger_]"
#}
puts "Creating sources..."
CreateSources
ConfigureRoutesAndRouters
CreateQueueMonitors
puts "Starting Simulation..."
Run


