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 is a single queue
object per duplex link; you can cannot set the parameters
asymmetrically). The following parameters can be changed, and are
defined in the NS manual (see Section 7.3):
set queue0 [[$ns link $nodeA $nodeB] queue]
$queue0 set gentle_ 0
$queue0 set queue-in-bytes_ 0
$queue0 set limit_ 75
$queue0 set maxthresh_ 20
$queue0 set thresh_ 7
$queue0 set linterm_ 11
$queue0 set q_weight_ 0.004
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 additional section that lists all
of the events that will be delivered during your experiment:
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.
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:
where the time parameter is one of:
tevc -e pid/eid time objname event [args ...]
For example, you could issue this sequence of events.
- now
- +seconds (floating point or integer)
- [[[[yy]mm]dd]HH]MMss
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:
NS File: $ns at 3.0 "$link0 down"
tevc: tevc -e pid/eid +3.0 link0 down
In "ns" script: $link0 bandwidth 10Mb duplex $link0 delay 10ms $link0 plr 0.05 With "tevc": tevc ... link0 modify bandwidth=20000 # In kbits/second; 20000 = 20Mbps tevc ... link0 modify delay=10ms # In msecs (the "ms" is ignoredd) tevc ... link0 modify plr=0.1 Both: $link0 up $link0 down
$queue0 set queue-in-bytes_ 0 $queue0 set limit_ 75 $queue0 set maxthresh_ 20 $queue0 set thresh_ 7 $queue0 set linterm_ 11 $queue0 set q_weight_ 0.004
$cbr0 start $cbr0 set packetSize_ 512 $cbr0 set interval_ 0.01 $cbr0 set rate_ 10Mbs $cbr0 stop
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:
Then in your NS file a set of static events to run these commands:
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"
If you want to schedule starts and stops using dynamic events:
$ns at 10 "$prog0 start"
$ns at 20 "$prog1 start"
$ns at 30 "$prog1 stop"
Some points worth mentioning:
tevc -e testbed/myexp now prog0 start "command=/bin/ls /tmp"
tevc -e testbed/myexp now prog1 start "command=sleep 60"
tevc -e testbed/myexp +20 prog1 stop