Dear all, I wanted to implement a Round Robin packet scheduler just following the process in the book Introduction to Network Simulator ns2 from Ekran Hossain:
According to the process I have created the following *.cc and *.h files: *//classifier-flow.h* #ifndef ns_gw_flow_classifier_h #define ns_gw_flow_classifier_h #include "packet.h" #include "ip.h" #include "classifier.h" class FlowClassifier : public Classifier { protected: int classify(Packet *p); }; #endif *//classifier-flow.cc* #include "gw_flow_classifier.h" #include <stdlib.h> static class FlowClassifierClass : public TclClass { public: FlowClassifierClass() : TclClass("Classifier/Flow") {} TclObject* create(int, const char*const*) { return (new FlowClassifier()); } } class_flow_classifier; int FlowClassifier::classify(Packet *p) { return hdr_ip::access(p)->flowid(); } *//pkt-sched.h* #ifndef ns_gw_pkt_sch_h #define ns_gw_pkt_sch_h #include "packet.h" #include "ip.h" #include "connector.h" #include "queue.h" #define NS 10 class PktScheduler : public Connector { public: PktScheduler(); virtual void handle(Event*); virtual void recv(Packet*, Handler*); protected: void send(int fid, Handler* h); virtual void resume(); int getFlowID(Packet* p) {return hdr_ip::access(p)->flowid();}; virtual int nextID() = 0; Handler* qh_[NS]; Packet* pkt_[NS]; int blocked_; int active_flow_id_; }; //RR class RRScheduler : public PktScheduler { public: RRScheduler(); private: virtual int nextID(); int current_id_; }; #endif *//pkt-sched.cc* #include "gw_pkt_sch.h" PktScheduler::PktScheduler() { int i; for (i=0;i<NS ;i++) { pkt_[i] = 0; qh_[i]=0; } blocked_ = 0;active_flow_id_ = -1; } void PktScheduler::recv(Packet* p, Handler* h) { int fid = getFlowID(p); pkt_[fid] = p;qh_[fid] = h; if (!blocked_) { send(fid,this); blocked_ = 1; active_flow_id_ = fid; } } void PktScheduler::send(int fid_idx, Handler* h) { Connector::send(pkt_[fid_idx],h); pkt_[fid_idx] = 0; } void PktScheduler::handle(Event*) { resume(); } void PktScheduler::resume() { qh_[active_flow_id_]->handle(0); int index = nextID(); blocked_ = 0; if (index >= 0) { send(index,this); blocked_ = 1; active_flow_id_ = index; } } //RR RRScheduler::RRScheduler() { current_id_ = -1; } static class RRSchedulerClass: public TclClass { public: RRSchedulerClass() : TclClass("PktScheduler/RR") {} TclObject* create(int, const char*const*) { return (new RRScheduler()); } } class_rr_scheduler; int RRScheduler::nextID() { int count = 0; current_id_++;current_id_ %= NS; while((pkt_[current_id_] == 0)&&(count < NS)){ current_id_++;current_id_ %= NS; count++; } if (count == NS) return -1; else{ return current_id_; } } *And the following Otcl file:* *#ns-link.tcl* Class LinkSch -superclass Link LinkSch instproc init {src dst bw delay num_queues} { $self next $src $dst $self instvar link_ queue_ head_ toNode_ ttl_ $self instvar drophead_ $self instvar num_queues_ sch_ flow_clsfr_ set ns [Simulator instance] set head_ [new Connector] set drophead_ [new Connector] set link_ [new DelayLink] set ttl_ [new TTLChecker] set flow_clsfr_ [new Classifier/Flow] set sch_ [new PktScheduler/RR] set num_queues_ $num_queues $head_ set link_ $self $drophead_ target [$ns set nullAgent_] $head_ target $flow_clsfr_ for {set i 0} {$i < $num_queues_} {incr i} { set queue_($i) [new Queue/DropTail] $queue_($i) target $sch_ $queue_($i) drop-target $drophead_ } $sch_ target $link_ $link_ target $ttl_ $link_ drop-target $drophead_ $link_ set bandwidth_ $bw $link_ set delay_ $delay $ttl_ target [$dst entry] $ttl_ drop-target $drophead_ } LinkSch instproc add-flow { fid } { $self instvar queue_ flow_clsfr_ $flow_clsfr_ install $fid $queue_($fid) } Simulator instproc sch-link { n1 n2 bw delay num_queues} { $self instvar link_ queueMap_ nullAgent_ useasim_ set sid [$n1 id] set did [$n2 id] set link_($sid:$did) [new LinkSch $n1 $n2 $bw $delay $num_queues] set pushback 0 $n1 add-neighbor $n2 $pushback } Simulator instproc add-flow { n1 n2 prio } { $self instvar link_ set sid [$n1 id] set did [$n2 id] $link_($sid:$did) add-flow $prio } *The output of the compilation is correct. However, when I try to simulate this tcl script:* set num_queues [lindex $argv 0] set ns [new Simulator] set f [open book.tr w] $ns trace-all $f set n1 [$ns node] set n2 [$ns node] set n3 [$ns node] $ns duplex-link $n1 $n2 5Mb 2ms DropTail $ns duplex-link $n2 $n3 5Mb 2ms DropTail $ns sch-link $n1 $n3 5Mb 2ms 10 $ns simplex-link $n3 $n1 5Mb 2ms DropTail for {set i 0} {$i < $num_queues} {incr i} { $ns add-flow $n1 $n3 $i set tcp($i) [new Agent/TCP] set sink($i) [new Agent/TCPSink] set ftp($i) [new Application/FTP] $tcp($i) set fid_ $i $ns attach-agent $n1 $tcp($i) $ns attach-agent $n3 $sink($i) $ftp($i) attach-agent $tcp($i) $ns connect $tcp($i) $sink($i) $ns at 0.0 "$ftp($i) start" } proc show_tcp_seqno {} { global tcp num_queues for {set i 0} {$i < $num_queues} {incr i} { puts "The final tcp($i) sequence number is [$tcp($i) set t_seqno_]" } } $ns at 10.0 "show_tcp_seqno" $ns at 10.1 "$ns halt" $ns run *I get the following error:* * * can't read "queue_": variable is array while executing "return $queue_" (procedure "_o59" line 3) (Link queue line 3) invoked from within "$link_($qn) queue" (procedure "_o3" line 20) (Simulator run line 20) invoked from within "$ns run" (file "book.tcl" line 34) I have notice that when I comment the following lines in ns-link.tcl file the error disappear but I do not know if it is correct or not to do it, or there is a smoother way to fix the problem: # # Also reset every queue # foreach qn [array names link_] { set q [$link_($qn) queue] $q reset } I use ns2 v2.34 on Ubuntu 10.04 64 bits OS. yes, I've read the FAQ, ns-problems page, and manual and I couldn't find the answer there. Thanks, -- Ricard Alegre http://wirelessatcom.uab.es/ricardalegre.htm -- Ricard Alegre http://wirelessatcom.uab.es/ricardalegre.htm