1
votes

i am using Ns2 and tcl script.In the following code i want to use the global variable rate12 which has the value of 2Mb in the expression

 if { $queuesize>16 } {
     set RL [expr $Rc * $fdec * $hf]
    set rate12 [expr $rate12 * $RL]
    puts $rate12
 }

found from within proc record. but it displays the following error:

ns: record _o104 file5: invalid bareword "Mb"
in expression "4_@_Mb * 0.40000000000000002";
should be "$Mb" or "{Mb}" or "Mb(...)" or ...
    (parsing expression "4Mb * 0.40000000000000...")
    invoked from within
"expr $rate12 * $RL"
    (procedure "record" line 26)
    invoked from within
"record _o104 file5"

how can i fix the error?

The whole code is:

#Create a simulator object

set ns [new Simulator]

 global rate02 
 global rate12 
 global rate23 
 global rate32 

#Define different colors for data flows (for NAM)
$ns color 1 Blue
$ns color 2 Red
$ns color 3 Green

#Open the NAM trace file
set nf [open out.nam w]
$ns namtrace-all $nf
# constants
global Rc 
global Fdec
global hf 

#Define a 'finish' procedure
proc finish {} {
    global ns nf
    $ns flush-trace
    #Close the NAM trace file
    close $nf
    #Execute NAM on the trace file
    exec nam out.nam &
    exit 0
}

#Create four nodes
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]

set rate02 2Mb
set rate12 4Mb
set rate23 2Mb
set rate32 0.1Mb

#Create links between the nodes
$ns duplex-link $n0 $n2 $rate02 10ms RED
$ns duplex-link $n1 $n2 $rate12 10ms DropTail
$ns duplex-link $n2 $n3 $rate23 20ms DropTail
$ns duplex-link $n3 $n2 $rate32 10ms DropTail

#Set Queue Size of link (n2-n3) to 10
$ns queue-limit $n2 $n3 16

#Give node position (for NAM)
$ns duplex-link-op $n0 $n2 orient right-down
$ns duplex-link-op $n1 $n2 orient right-up
$ns duplex-link-op $n2 $n3 orient right

#Monitor the queue for link (n2-n3). (for NAM)
$ns duplex-link-op $n2 $n3 queuePos 0.5

#creat file record infomation at queues

set queue03 [$ns monitor-queue $n2 $n3 [open qsize03.tr w] 0.05]
set qsize03 [open qsize03.tr w]


proc record {queue qsize} {
        global ns
        #set ns [Simulator instance]
        set time 0.1
        set now [$ns now]
        #print current qsize in $queuesize
        $queue instvar parrivals_ pdepartures_ bdros_ bdepartures_ pdrops_
        #set queuesize [expr $parrivals_ - $pdepartures_ - $pdrops_]
        set queuesize $parrivals_
        puts $queuesize
        puts $qsize "$now [expr $parrivals_ - $pdepartures_ - $pdrops_]"
        #puts "$now [expr $parrivals_ - $pdepartures_ - $pdrops_]"
        set $bdepartures_ 0

        set Rc 2
        set fdec 0.4
        set hf 0.5
        global rate12
        set n0 [$ns node]
        set n1 [$ns node]
        set n2 [$ns node]

        if { $queuesize>16 } {
        set RL [expr $Rc * $fdec * $hf]
        set rate12 [expr $rate12 * $RL]
        puts $rate12
        $ns duplex-link $n0 $n2 0.8Mb 10ms RED
        } elseif { $queuesize==20 } {
        puts "full"
        } else {
        puts "under"
        }

        $ns at [expr $now + $time] "record $queue $qsize"
}

#Setup a TCP connection
set tcp1 [new Agent/TCP]
$tcp1 set class_ 2
$ns attach-agent $n0 $tcp1
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp1 $sink
$tcp1 set fid_ 1
#########################################
#Setup a TCP connection
set tcp3 [new Agent/TCP]
$tcp3 set class_ 2
$ns attach-agent $n3 $tcp3
set sink2 [new Agent/TCPSink]
$ns attach-agent $n1 $sink2
$ns connect $tcp3 $sink2
$tcp3 set fid_ 3

#Setup a FTP over TCP connection
set ftp3 [new Application/FTP]
$ftp3 attach-agent $tcp3
$ftp3 set type_ FTP
############################################
#Setup a FTP over TCP connection
set ftp1 [new Application/FTP]
$ftp1 attach-agent $tcp1
$ftp1 set type_ FTP

#Setup a TCP connection
set tcp2 [new Agent/TCP]
$tcp2 set class_ 2
$ns attach-agent $n1 $tcp2
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp2 $sink
$tcp2 set fid_ 2

#Setup a FTP over TCP connection
set ftp2 [new Application/FTP]
$ftp2 attach-agent $tcp2
$ftp2 set type_ FTP

#Schedule events for the CBR and FTP agents
$ns at 0.1 "$ftp2 start"
$ns at 0.5 "record $queue03 $qsize03"
$ns at 1.0 "$ftp1 start"
$ns at 1.0 "$ftp3 start"
$ns at 4.0 "$ftp2 stop"
$ns at 4.5 "$ftp1 stop"
$ns at 4.5 "$ftp3 stop"

#Detach tcp and sink agents (not really necessary)
$ns at 4.5 "$ns detach-agent $n0 $tcp1 ; $ns detach-agent $n3 $sink"
$ns at 4.5 "$ns detach-agent $n1 $tcp2 ; $ns detach-agent $n3 $sink"

#Call the finish procedure after 5 seconds of simulation time
$ns at 5.0 "finish"
$ns run
2

2 Answers

4
votes

Tcl's expr command does not work with values that have a unit like Mb attached.

So it tries to interpret the value $rate12 which is 4Mb, but thats not a valid numerical literal, so you get the error. Combined with the fact that you do not brace your expresssions, e.g. you write:

set rate12 [expr $rate12 * $RL]

instead of

set rate12 [expr {$rate12 * $RL}]

you get double evaluation of the expr, which produces the misleading error message (and can be much slower).

To fix that, you need to do calculations on values without units, or write a small proc to do it with units included.

1
votes

The keyword global is meaningful only within the scope of a proc. To access rate12, at the beginning of the proc record, add the following line:

global rate12

That should fix your problem.

UPDATE

My bad, I did not see the global command in the middle of the proc. The problem is at the beginning you have:

set rate12 4Mb 

Then later on, in proc record:

set rate12 [expr $rate12 * $RL]

According to Tcl, 4Mb is not a number. I suggest the following fix:

set rate12 4

Or, more descriptive:

set rateInMb12 4