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

Reply via email to