the following code
#Create a simulator object
set ns [new Simulator]
#Open the nam trace file
set nf[open out.nam w]
$ns namtrace-all $nf
#Define a 'finish' procedure
proc finish {} {
global ns nf
$ns flush-trace
#Close the trace file
close $nf
#Execute namon the trace file
exec nam–a out.nam&
exit 0
}
#Create two nodes
set n0 [$ns node]
set n1 [$ns node]
#Create a duplex link between the nodes
$ns duplex-link $n0 $n1 1Mb 10ms DropTail
#Call the finish procedure after 5 seconds of simulation time
$ns at 5.0 "finish"
#Run the simulation
$ns run
produces this error
can't read "nffile5": no such variable
while executing
"set nf[open out.nam w]"
(file "Desktop/sample.tcl" line 4)
it is my first time in tcl. so what is the problem.
i just run this by this statement: > ns sample.tcl
You're missing a space after the variable name:
set nf [open out.nam w]
Tcl is very dependent on proper use of whitespace. The entire language can be described in 12 rules, listed here. Rule 3: "Words of a command are separated by white space (except for newlines, which are command separators)."
What was actually happening in your script:
Tcl breaks the command into 2 words: the command set and the argument nf[open out.nam w]
the command in brackets is executed and the result (the filehandle name returned is file5) is substituted.
the set command is executed with its one argument, nffile5
when given a single argument, the set command will return the value of the given variable.
since you never assigned a variable by that name, set returns an error.
Related
I've created the following code to run a tcl script multiple times in NS2.The code is executed many times but the start and stop times for the traffic generator doesn't change from one run to the other .What is wrong with my code?
set ns [new Simulator]
for {set i 1} {$i<5} {incr i} {
.....
set min 0
set max 10
set min1 10
set max1 20
set start [expr rand()*($max-$min)]
set stop [expr rand()*($max1-$min1)+$min1]
$ns at $start "ftp start"
$ns at $stop "ftp stop"
puts $outfile "$start $stop"
}
$ns run
Thanks in advance !
What does eval mean in the following code?
proc poissontraffic { src dst interval starttime } {
global ns_ node_
set udp($src) [new Agent/UDP]
eval $ns_ attach-agent \$node_($src) \$udp($src)
set null($dst) [new Agent/Null]
eval $ns_ attach-agent \$node_($dst) \$null($dst)
set expl($src) [new Application/Traffic/Exponential]
eval \$expl($src) set packetSize_ 70
eval \$expl($src) set burst_time_ 0
# idle_time + pkt_tx_time = interval
eval \$expl($src) set idle_time_ [expr $interval*1000.0-70.0*8/250]ms
eval \$expl($src) set rate_ 250k
eval \$expl($src) attach-agent \$udp($src)
eval $ns_ connect \$udp($src) \$null($dst)
$ns_ at $starttime "$expl($src) start"
}
The eval command concatenates its arguments and evaluates the resulting string as a Tcl script. The concatenation is done by stripping spaces from either end of each argument and then joining them together with a single space between.
In the given code, for example,
eval $ns_ connect \$udp($src) \$null($dst)
effectively does two rounds of substitutions, once to fill in $ns_, $src and $dst, and again to read from $udp(...), $null(...), and run a command.
You can probably replace it with this:
$ns_ connect $udp($src) $null($dst)
That'll only be a problem if $ns_ is a multi-word value. Since this is fundamentally OTcl where object names are usually well-behaved, it probably isn't and all the evals will be adding is confusion, slowness and insecurity.
Hy guy i tried to invoke this tcl in the terminal but it gave me this error
num_nodes is set 0
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
can't read "node_(0)": no such variable
while executing
"$node_(0) set X_ 133.516460138239"
(file "/tmp/mob.tcl" line 4)
invoked from within
"source.orig /tmp/mob.tcl"
("uplevel" body line 1)
invoked from within
"uplevel source.orig [list $fileName]"
invoked from within
"if [$instance_ is_http_url $fileName] {
set buffer [$instance_ read_url $fileName]
uplevel eval $buffer
} else {
uplevel source.orig [list $fileName]
..."
(procedure "source" line 8)
invoked from within
"source "/tmp/mob.tcl" "
(file "mobilita_source.tcl" line 125)
And the tcl file is
# Define ions
set val(chan) Channel/WirelessChannel ;# channel type
set val(prop) Propagation/TwoRayGround ;# radio-propagation model
set val(netif) Phy/WirelessPhy ;# network interface type
set val(mac) Mac/802_11 ; # MAC type
Mac/802_11 set RTSThreshold_ 500 ;
Mac/802_11 set dataRate_ 24Mb ;
Mac/802_11 set basicRate_ 6Mb ;
Mac/802_11 set CWMin_ 31 ;
Mac/802_11 set CWMAX_ 1023 ;
Mac/802_11 set SlotTime_ 0.000009 ;
Mac/802_11 set SIFS_ 0.000016 ;
Mac/802_11 set ShortRetryLImit_ 7 ;
Mac/802_11 set LOngRetryLimit_ 7 ;
set val(ifq) Queue/DropTail/PriQueue ;# interface queue type
set val(ifqlen) 50 ;# max packet in ifq
set val(ll) LL ;# link layer type
set val(ant) Antenna/OmniAntenna ;# antenna model
set val(adhocRouting) AODV ;# routing protocol
set val(x) 250 ;# X dimension of the topography
set val(y) 250 ;# Y dimension of the topography
set val(tr) esercizio1.tr ;# trace file
set val(rate) [lindex $argv 0] ;
set val(nn) [lindex $argv 1] ;# how many nodes are simulated
set val(stop) [lindex $argv 3] ;# simulation time
set val(seed) 0.0
# Main Program
# Initialize Global Variables
# create simulator instance
set ns_ [new Simulator]
# define topology
set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)
# create trace object for ns and nam
set tracefd [open $val(tr) w]
$ns_ trace-all $tracefd
$ns_ use-newtrace
# Create God
set god_ [create-god $val(nn)]
# define how node should be created
#global node setting
$ns_ node-config -adhocRouting $val(adhocRouting) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-channelType $val(chan) \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace ON
# Create the specified number of nodes [$val(nn)] and "attach" them to the channel
for {set i 0} {$i < $val(nn) } {incr i} {
set node_($i) [$ns_ node]
}
# Define node positions
source "/tmp/mob.tcl"
# Define traffic flows
source "traffic"
for {set i 0} {$i < 4 } {incr i} {
$cbr_($i) set interval_ [ expr 1 /$rate ]
}
# Tell nodes when the simulation ends
for {set i 0} {$i < $val(nn) } {incr i} {
$ns_ at $val(stop).000000001 "$node_($i) reset";
}
$ns_ at $val(stop).000000001 "puts \"NS EXITING...\" ; $ns_ halt"
puts "Starting Simulation..."
$ns_ run
i invoked the ns mobilita_source from terminal but it describe me this so i think it could be for the path /tmp in the mobilita_souce.tcl file. In tmp i noticed that the file is present.
The variable node_(0) is not set, so the variable is unreadable. That means that the code to set it did not run, perhaps because the variable val(nn) contains 0, or perhaps because it contains something other value — possibly non-numeric — that sorts less than 1; the empty string is such a value. The value of val(nn) comes from lindex $argv 1, so it is the second argument after the Tcl script that you passed to the executable to invoke the program (assuming it's tclsh-like).
If there are insufficient arguments, you'll get an empty string from the lindex (for backward-compatibility reasons, and out-of-range lindex produces an empty string instead of throwing an error). You are advised to explicitly check that sufficient arguments were passed in:
if {[llength $argv] < 4} {
error "missing arguments, needs: rate, nn, ??, seed"
}
You can then (assuming Tcl 8.5 or 8.6) use lassign to write those to variables; it's a little clearer than a bunch of set … [lindex $argv …] and easier to get correct:
# your posted code ignores one argument...
lassign $argv val(rate) val(nn) ?? val(seed)
In 8.4 and before (outdated versions now) then you'd instead do:
foreach $argv {val(rate) val(nn) ?? val(seed)} break
But that's really not very clear.
I am very naive to NS2 use and was trying to implement CBR over UDP in NS2 . I wrote the following code:
set ns [new Simulator]
set tracefile [open out.tr w]
$ns trace-all $tracefile
set nf [open out.nam w]
$ns namtrace-all $nf
#should be "proc name args body"
#while executing
#"proc finish {}"
proc finish {}
{
global ns tracefile nf
$ns flush-trace
close $nf
close $tracefile
exec nam out.nam &
exit 0
}
set n0 [$ns node]
set n1 [$ns node]
$ns simplex-link $n0 $n1 1Mb 10ms DropTail
set udp0 [new Agent/UDP]
$ns attach-agent $n0 $udp0
set cbr[new Application/Traffic/CBR]
$cbr attach-agent $udp0
set null0 [new Agent/Null]
$ns attach-agent $n1 $null0
$ns connect $udp0 $null0
$ns at 1.0 "$cbr start"
$ns at 3.0 "finish"
$ns run
The error being shown is commented above the proc finish procedure. I tried to look for errors but couldn't find one. What I have done is written this as a Tcl script and for doing ns filename.tcl to run .
Tcl as a language treats newline as being significant; it marks the end of a sequence of words that form a command invocation. Because proc is actually just a normal Tcl command (that happens to create commands using a script as implementation) and not some special syntax, if you do:
proc finish {}
Then you are supplying proc with one fewer arguments than it needs according to its definition. At that point, it complains, and that complaint is what you have observed. (proc does not know that you've decided to put a word that you want used as the script body on the next line; that's a level of smartness that Tcl explicitly eschews as a matter of policy, in that Tcl has no real special syntactic forms at all.)
The way to fix this is to write your code using “one true brace” style, which Tcl strongly favors:
proc finish {} {
# put the body in here
}
Failing that, you can use backslashes to write things differently:
proc finish {} \
{
# body...
}
However, hardly any Tclers seem to favor that one. (After all, it requires more typing.)
I have two tcl files. one is main tcl file(main.tcl) and another one is like helper file(help.tcl) for main tcl file.I want to execute that helperfile from main file while execution of main file.I use the command "source filename" for this.but i got some errors.here i post both tcl files and what is the error occured on execution. Please help me to solve this...
Error
num_nodes is set 4
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
INITIALIZE THE LIST xListHead
Enter Source Node (0 to 4)
0
Enter Destination Node (0 to 4)
3
SORTING LISTS ...DONE!
channel.cc:sendUp - Calc highestAntennaZ_ and distCST_
highestAntennaZ_ = 1.5, distCST_ = 716.1
ns: proc1: can't read "n0": no such variable
while executing
"attach-CBR-traffic $n0 $sink1 64 0.07"
invoked from within
"set inf0_1[attach-CBR-traffic $n0 $sink1 64 0.07]"
(file "final.tcl" line 1)
invoked from within
"source.orig final.tcl"
("uplevel" body line 1)
invoked from within
"uplevel source.orig [list $fileName]"
invoked from within
"if [$instance_ is_http_url $fileName] {
set buffer [$instance_ read_url $fileName]
uplevel eval $buffer
} else {
uplevel source.orig [list $fileName]
..."
(procedure "source" line 8)
invoked from within
"source final.tcl"
(procedure "proc1" line 6)
invoked from within
"proc1"
In the file Main.tcl:
set val(chan) Channel/WirelessChannel ;# Channel Type
set val(prop) Propagation/TwoRayGround ;# radio-propagation model
set val(netif) Phy/WirelessPhy ;# network interface type
set val(mac) Mac/802_11 ;# MAC type
set val(ifq) CMUPriQueue ;# interface queue type
set val(ll) LL ;# link layer type
set val(ant) Antenna/OmniAntenna ;# antenna model
set val(ifqlen) 340 ;# max packet in ifq
set val(nn) 4 ;# number of mobilenodes
set val(rp) DSR ;# routing protocol
set val(x) 630 ;# X axis distance
set val(y) 570 ;# Y axis distance
set opt(energymodel) EnergyModel ;# Initial Energy
set opt(initialenergy) 100 ;# Initial energy in Joules
set ns [new Simulator]
set nam1 [open nam11.nam w]
$ns namtrace-all-wireless $nam1 $val(x) $val(y)
set trace1 [open trace11.tr w]
$ns trace-all $trace1
$ns use-newtrace
set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)
create-god $val(nn)
Phy/WirelessPhy set Pt_ 0.81
$ns node-config -adhocRouting $val(rp) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace ON \
-movementTrace ON \
-rxPower 0.36 \
-txPower 0.14 \
-channelType $val(chan) \
-initialEnergy $opt(initialenergy) \
-energyModel $opt(energymodel) \
for { set i 0 } {$i < $val(nn)} { incr i } {
set n($i) [$ns node]
$n($i) random-motion 0
$n($i) color black
$ns initial_node_pos $n($i) 30
}
for { set i 0 } { $i < $val(nn)} { incr i } {
$ns at 0.0 "$n($i) color black"
$ns at 0.0 "$n($i) label-color maroon"
}
$ns at 0.0 "$n(0) setdest 220.00 210 3000"
$ns at 0.0 "$n(1) setdest 320.00 310 3000"
$ns at 0.0 "$n(2) setdest 420.00 110 3000"
$ns at 0.0 "$n(3) setdest 520.00 210 3000"
for {set i 0} {$i<$val(nn)} {incr i} {
set sink($i) [new Agent/LossMonitor]
$ns attach-agent $n($i) $sink($i)
}
proc attach-CBR-traffic { node sink size itval} {
#Get an instance of the simulator
set ns_ [Simulator instance]
set udp [new Agent/UDP]
$ns_ attach-agent $node $udp
#Create a CBR agent and attach it to the node
set cbr [new Application/Traffic/CBR]
$cbr attach-agent $udp
$cbr set packetSize_ $size ;#sub packet size
$cbr set interval_ $itval
#Attach CBR source to sink;
$ns_ connect $udp $sink
return $cbr
}
set cbr001 [attach-CBR-traffic $n(0) $sink(1) 256 0.082]
$ns at 1.0 "$cbr001 start"
$ns at 1.001 "$cbr001 stop"
set cbr001 [attach-CBR-traffic $n(1) $sink(3) 256 0.082]
$ns at 1.002 "$cbr001 start"
$ns at 1.003 "$cbr001 stop"
# neighbor node calculation
set nbr [open Neighbor w]
puts $nbr "\t\t\t\t\tNeighbor Detail"
puts $nbr "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts $nbr "\tNode\t\tNb node\t\tNode-Xpos\tNode-Ypos\tNb-Xpos\t\tNb-Ypos\t\tDistance(d)"
puts $nbr "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
close $nbr
#~~~~~~~~~~~~~~~~ Calculation of neighbor nodes of all node~~~~~~~~~~~~~~~~~~~
proc distance { n1 n2 nd1 nd2} {
global c n bnd
set nbr [open Neighbor a]
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
if {$d<300} {
if {$nd2!=$nd1} {
puts $nbr "\t$nd1\t\t$nd2\t\t$x1\t\t$y1\t\t$x2\t\t$y2\t\t$d"
}
}
close $nbr
}
for {set i 0} {$i <$val(nn)} {incr i} {
for {set j 0} {$j <$val(nn)} {incr j} {
$ns at 1.002 "distance $n($i) $n($j) $i $j"
}
}
# For Input
set f 1
while {$f} {
puts "Enter Source Node (0 to 4)"
gets stdin src
puts "Enter Destination Node (0 to 4)"
gets stdin dst
if {$src>=0 && $src<5 && $dst>=0 && $dst<5 && $src!=$dst} {
set f 0
set sd [open srcdst w]
puts $sd "$src $dst"
close $sd
} else {
puts "\n\t---------Enter Proper Input-------\n"
}
}
#minimum
proc proc1 {} {
exec awk -f distance.awk srcdst Neighbor &
exec awk -f mm.awk snd &
exec awk -f mnode.awk min snd &
exec awk -f final.awk srcdst mnode &
source final.tcl
}
$ns at 1.5 "proc1"
proc proc2 {} {
global ns trace1 nam1
$ns flush-trace
close $trace1
close $nam1
exec nam nam11.nam &
exit 0
}
$ns at 3.0 "proc2"
$ns run
In the file final.tcl:
set inf0_1[attach-CBR-traffic $n0 $sink1 64 0.07]
$ns at2.1 "$inf0_1 start"
$ns at2.3 "$inf0_1 stop"
$ns at2.1 "$n(0) color green4"
$ns at2.4 "$ns trace-annotate\"Node-0 send data to its neighbor1\""
set inf1_3[attach-CBR-traffic $n1 $sink3 64 0.07]
$ns at2.1 "$inf1_3 start"
$ns at2.3 "$inf1_3 stop"
$ns at2.1 "$n(1) color green4"
$ns at2.4 "$ns trace-annotate\"Node-1 send data to its neighbor3\""
There doesn't seem to be anywhere in your main.tcl file where you source help.tcl. However, in the error message it appears that the file you claim to be help.tcl is actually named final.tcl. Assuming this is what you mean then I can diagnose the error.
The problem is that in your final.tcl file, the first line tries to execute this statement:
set inf0_1 [attach-CBR-traffic $n0 $sink1 64 0.07]
# ^
# |
# BTW, unrelated to the error, there is also a missing space here which
# is probably not what you intended.
The problem with that statement is that the variables n0 and sink1 are undefined.
Updated Answer
OK, there seem to be lots of misconceptions in your understanding of Tcl. I highly recommend reading the documentation of the Tcl language. Fortunately for you, unlike C or Perl or almost any other language, the complete documentation of tcl syntax is only a single page: http://www.tcl.tk/man/tcl/TclCmd/Tcl.htm. Note specifically rule number 8 (variable substitution).
First thing you need to know that's wrong with your script is what the error message tells you: you have not defined the variable n0 anywhere in your program (nor have you defined sink1). There is however a global variable n which happens to be an array. From you comment it looks like this is what you mean when you're trying to access n0. If so, the correct syntax is given in rule number 8: arrays are accessed using the arrayname(index) syntax. Before we go further I'd like to remind you that what Tcl calls arrays are technically associative arrays (in other languages they are sometimes known as hashes or maps) so the index can be a string. Now, having said that, the correct syntax for accessing n is:
set inf0_1 [attach-CBR-traffic $n(0) $sink(1) 64 0.07]
# ^ ^
But this still won't work. If you try this it will still complain about n and sink being undefined. That's because of how tcl scoping rules work. Inside a function, only local variables are visible. Global variables are not available inside functions unless you explicitly ask tcl to import them. To access global variables you have two options:
First, the traditional way: use the global command to import the global variables. You can either do it in the proc that sources the final.tcl file:
proc proc1 {} {
global n sink
# ...
source final.tcl
}
or you can do it in the final.tcl file itself:
global n sink
set inf0_1 [attach-CBR-traffic $n(0) $sink(1) 64 0.07]
# ...
The second method is to access the global variables using the global namespace ::. This way you don't need to import the variables using the global command:
set inf0_1 [attach-CBR-traffic $::n(0) $::sink(1) 64 0.07]
Fixing all the issues I highlighted above should get your code running (assuming I've guessed your intentions correctly). However I strongly suggest reading the tcl man pages and familiarize yourself with tcl to avoid future bugs. At minimum you should understand the syntax rules, the man page for set and the man page for proc:
http://www.tcl.tk/man/tcl/TclCmd/Tcl.htm
http://www.tcl.tk/man/tcl/TclCmd/set.htm
http://www.tcl.tk/man/tcl/TclCmd/proc.htm
The following page is also a good introduction to tcl: An Introduction to Tcl Scripting