Emulab Tutorial - A More Advanced Example

Here is a slightly more complex example demonstrating the use of RED queues, traffic generation, and the event system. Where possible, we adhere to the syntax and operational model of ns-2, as described in the NS manual.

What follows is a sample NS file that demonstrates the above features, with annotations where appropriate. First we define the 2 nodes in the topology:

	set nodeA [$ns node]
	set nodeB [$ns node]			

Next define a duplex link between nodes nodeA and nodeB. Instead of a standard DropTail link, it is declared to be a Random Early Detection (RED) link. While this is obviously contrived, it allows us to ignore routing issues within this example.

	set link0 [$ns duplex-link $nodeA $nodeB 100Mb 0ms RED]

Each link is has an NS "Queue" object associated with it, which you can modify to suit your needs (currently, there are two queue objects per duplex link; one for each direction. You need to set the parameters for both directions, which means you can set the parameters asymmetrically if you want). The following parameters can be changed, and are defined in the NS manual (see Section 7.3). Note, only duplex links have queue objects, lans do not.

	set queue0 [[$ns link $nodeA $nodeB] queue]
	$queue0 set gentle_ 0
	$queue0 set red_ 0
	$queue0 set queue-in-bytes_ 0
	$queue0 set limit_ 50
	$queue0 set maxthresh_ 15
	$queue0 set thresh_ 5
	$queue0 set linterm_ 10
	$queue0 set q_weight_ 0.002

A UDP agent is created and attached to nodeA, then a CBR traffic generator application is created, and attached to the UDP agent:

	set udp0 [new Agent/UDP]
	$ns attach-agent $nodeA $udp0

	set cbr0 [new Application/Traffic/CBR]
	$cbr0 set packetSize_ 500
	$cbr0 set interval_ 0.005
	$cbr0 attach-agent $udp0

A TCP agent is created and also attached to nodeA, then a second CBR traffic generator application is created, and attached to the TCP agent:

	set tcp0 [new Agent/TCP]
	$ns attach-agent $nodeA $tcp0

	set cbr1 [new Application/Traffic/CBR]
	$cbr1 set packetSize_ 500
	$cbr1 set interval_ 0.005
	$cbr1 attach-agent $tcp0

You must define traffic sinks for each of the traffic generators created above. The sinks are attached to nodeB:

	set null0 [new Agent/Null]
	$ns attach-agent $nodeB $null0

	set null1 [new Agent/TCPSINK]
	$ns attach-agent $nodeB $null1

Then you must connect the traffic generators on nodeA to the traffic sinks on nodeB:

	$ns connect $udp0 $null0  
	$ns connect $tcp0 $null1

Here is a good example for NSE FullTcp traffic generation. The following code snippet attaches an FTP agent that drives a Reno FullTcp on NodeA:

	set tcpfull0 [new Agent/TCP/FullTcp]
	$ns attach-agent $nodeA $tcpfull0

	set ftp0 [new Application/FTP]
	$ftp0 attach-agent $tcpfull0

You must then define the sink FullTcp endpoint and call the method "listen" making this agent wait for an incoming connection:

	set tcpfull1 [new Agent/TCP/FullTcp/Sack]
	$tcpfull1 listen
	$ns attach-agent $nodeB $tcpfull1

Like all other source-sink traffic generators, you need to connect them:

	$ns connect $tcpfull0 $tcpfull1

Lastly, a set of events to control your applications and link characteristics:

	$ns at 60.0  "$cbr0  start"
	$ns at 70.0  "$link0 bandwidth 10Mb duplex"
	$ns at 80.0  "$link0 delay 10ms"
	$ns at 90.0  "$link0 plr 0.05"
	$ns at 100.0 "$link0 down"
	$ns at 110.0 "$link0 up"
	$ns at 115.0 "$cbr0  stop"

	$ns at 120.0 "$ftp0 start"
	$ns at 140.0 "$tcpfull0 set segsize_ 256; $tcpfull0 set	segsperack_ 2"
	$ns at 145.0 "$tcpfull1 set nodelay_ true"
	$ns at 150.0 "$ftp0 stop"
	
	$ns at 120.0 "$cbr1  start"
	$ns at 130.0 "$cbr1  set packetSize_ 512"
	$ns at 130.0 "$cbr1  set interval_ 0.01"
	$ns at 140.0 "$link0 down"
	$ns at 150.0 "$cbr1  stop"

When you receive email containing the experiment setup information (as described in Beginning an Experiment), you will notice an additonal section that gives a summary of the events that will be delivered during your experiment:

Event Summary:
--------------
Event count: 18
First event: 60.000 seconds
Last event: 160.000 seconds 

You can get a full listing of the events for your experiment by running tbreport -v pid eid on users.emulab.net. This report will include a section like this:

Event List:
Time         Node         Agent      Type       Event      Arguments
------------ ------------ ---------- ---------- ---------- ------------ 
60.000       nodeA        cbr0       TRAFGEN    START      PACKETSIZE=500
                                                           RATE=100000
                                                           INTERVAL=0.005
70.000       tbsdelay0    link0      LINK       MODIFY     BANDWIDTH=10000
80.000       tbsdelay0    link0      LINK       MODIFY     DELAY=10ms
90.000       tbsdelay0    link0      LINK       MODIFY     PLR=0.05
100.000      tbsdelay0    link0      LINK       DOWN       
110.000      tbsdelay0    link0      LINK       UP         
115.000      nodeA        cbr0       TRAFGEN    STOP       
120.000      nodeA        cbr1       TRAFGEN    START      PACKETSIZE=500
                                                           RATE=100000
                                                           INTERVAL=0.005
120.000      nodeA        ftp0       TRAFGEN    MODIFY     $ftp0 start
130.000      nodeA        cbr1       TRAFGEN    MODIFY     PACKETSIZE=512
130.000      nodeA        cbr1       TRAFGEN    MODIFY     INTERVAL=0.01
140.000      tbsdelay0    link0      LINK       DOWN       
140.000      nodeA        tcpfull0   TRAFGEN    MODIFY     $tcpfull0 set segsize_ 256
140.000      nodeA        tcpfull0   TRAFGEN    MODIFY     $tcpfull0 set segsperack_ 2
145.000      nodeB        tcpfull1   TRAFGEN    MODIFY     $tcpfull1 set nodelay_ true
150.000      tbsdelay0    link0      LINK       UP         
150.000      nodeA        ftp0       TRAFGEN    MODIFY     $ftp0 stop
160.000      nodeA        cbr1       TRAFGEN    STOP		

The above list represents the set of events for your experiments, and are stored in the Emulab Database. When your experiment is swapped in, an event scheduler is started that will process the list, and send them at the time offset specified. In order to make sure that all of the nodes are actually rebooted and ready, time does not start ticking until all of the nodes have reported to the event system that they are ready. At present, events are restricted to system level agents (Emulab traffic generators and delay nodes), but in the future we expect to provide an API that will allow experimentors to write their own event agents.

Dynamic Scheduling of Events

NS scripts give you the ability to schedule events dynamically; an NS script is just a TCL program and the argument to the "at" command is any valid TCL expression. This gives you great flexibility in a simulated world, but alas, this cannot be supported in a practical manner in the real world. Instead, we provide a way for you to inject events into the system dynamically, but leave it up to you to script those events in whatever manner you are most comfortable with, be it a PERL script, or a shell script, or even another TCL script! Dynamic event injection is accomplished via the Testbed Event Client (tevc), which is installed on your experimental nodes and on users.emulab.net. The command line syntax for tevc is:

	tevc -e pid/eid time objname event [args ...]
where the time parameter is one of:
For example, you could issue this sequence of events.
	tevc -e testbed/myexp now cbr0 set interval_=0.2
	tevc -e testbed/myexp +10 cbr0 start
	tevc -e testbed/myexp +15 link0 down
	tevc -e testbed/myexp +17 link0 up
	tevc -e testbed/myexp +20 cbr0 stop
Some points worth mentioning:

Supported Events

This is a (mostly) comprehensive list of events that you can specify, either in your NS file or as a dynamic event on the command line. In the listings below, the use of "link0", "cbr0", etc. are included to clarify the syntax; the actual object names will depend on your NS file. Also note that when sending events from the command line with tevc, you should not include the dollar ($) sign. For example:
NS File: $ns at 3.0 "$link0 down"
tevc: tevc -e pid/eid +3.0 link0 down

Program Objects

We have added some extensions that allow you to use NS's at syntax to invoke arbitrary commands on your experimental nodes. Once you define a program object and initialize its command line and the node on which the command should be run, you can schedule the command to be started and stopped with NS at statements. To define a program object:

	set prog0 [new Program $ns]
	$prog0 set node $nodeA
	$prog0 set command "/bin/ls -lt >& /users/joe/logs/prog0"

	set prog1 [new Program $ns]
	$prog1 set node $nodeB
	$prog1 set command "/bin/sleep 60 >& /tmp/sleep.debug"
Then in your NS file a set of static events to run these commands:
	$ns at 10 "$prog0 start"
	$ns at 20 "$prog1 start"
	$ns at 30 "$prog1 stop"
If you want to schedule starts and stops using dynamic events:
	tevc -e testbed/myexp now prog0 start
	tevc -e testbed/myexp now prog1 start
	tevc -e testbed/myexp +20 prog1 stop
If you want to change the command that is run (override the command you specified in your NS file), then:
	tevc -e testbed/myexp now prog0 start COMMAND='ls >/tmp/foo'
Some points worth mentioning: