ns队列计算,转载自http://strongmaple.blog.163.com/blog/static/16424899120139294421832/

时间:2022-10-29 00:38:59

2013年10月29日  

2013-10-29 16:42:18|  分类: 默认分类|举报|字号 订阅

NS2  如何监控队列长度  建议方法2

方法1  只对RED有效

set q_n1_n2 [[$ns link $n1 $n2] queue]

set q_ $q_n1_n2

set queuefd [open q-Red_Queue.tr w]

$q_ trace curq_  ;#current queue

$q_ trace ave_  ;#average queue

$q_ attach $queuefd

方法2monitor-queue 对所有队列有效,只记录结果,,

注意queue_limit*meanpktsizes 才是统计结果

利用monitor-queue”可以监视指定链路的队列的实时变化情况,用法如下:

             set qm [$ns monitor-queue $s0 $r0 [open qm.out w] 0.01]
             $qm set size_
解释:

      1.$ns monitor-queue $n0 $n1 [open qm.out w] 0.01
        
依次的含义:$ns”表示ns对象,monitor-queue”ns对象的方法(也可以认为是固定的命令)用来创建队列监视的对象,$n0”"n1"表示链路的两个网络节点, "[open qm.out w]“表示打开文件,"0.01"表示监视队列的时间间隔。

     2.注意上面的命令返回的是一个对象,所以使用set将其赋值给了变量qm,利用此变量进行后续操作。

    3.$qm set size_              返回当前的队列大小。

   4.上面的还不能满足需求,需要将其放到一个函数中,下面的是一个较完整的例子:

........省略代码

set qf [open myfile.txt w]

proc record {} {

#声明全局变量,qf为记录队列大小随时间变化的文本文件

global   qm  ns qf

set    now   [$ns  now]

puts $qf  "$now    [$qm  set  size_]"

$ns  at  [expr  $now + 0.01]  "record"

}

set qm [$ns monitor-queue $n0 $n1 [open qm.out w] 0.01]

.......省略代码

$ns at 0.0 "record"

.......

$ns run

 

方法3:对所有队列有效,记录整个队列情况

 

ns队列计算,转载自http://strongmaple.blog.163.com/blog/static/16424899120139294421832/
 

queue_limit设置为10  这里刚好到n-1  也就是9

 

绘制曲线的时候使用gnuplot设置绘制数据的列就可以了,,

gnuplot> plot "qm.out" using 1:5

gnuplot> plot "qm.out" using 1:5 with lines

gnuplot>

 

其中qm.out结果格式可能比较复杂,需要自己分析

qm.out格式,,,

http://www.mathcs.emory.edu/~cheung/Courses/558-old/Syllabus/90-NS/trace.html

set file1 [open qm.out w]

 set qmon [$ns monitor-queue $n2 $n3 $file1 0.1]

 [$ns link $n2 $n3] queue-sample-timeout


 

 

方法4:修改源代码实现,,较复杂,通用


队列的输出

实现队列输出的思路:首先编写运行一个tcl脚本,读取脚本生成原的trace文件(out_rc_3.tr),在该trace文件中计算获取相应节点和队列长度(调用一些.h文件实现),然后将这些内容在生成一个trace文件(qlen.tr),为了阅读的方便在由gnuplot读取qlen.tr生成gnuplot图。

 

首先对NS2进行编译,查看是否有错:打开NS2,进入到相关路径,在该路径下分别输入make clean”make depend”make”命令符。

 

编译结束。没有出错在进行程序源代码的修改(红色为添加部分)。修改的步骤如下所示:

1.修改queue/priqueue.h文件

#include "trace.h"

class PriQueue : public DropTail {

public:

       PriQueue();

       int    command(int argc, const char*const* argv);

       void   recv(Packet *p, Handler *h);

       void   recvHighPriority(Packet *, Handler *);

       // insert packet at front of queue

       void filter(PacketFilter filter, void * data);

       // apply filter to each packet in queue,

       // - if filter returns 0 leave packet in queue

       // - if filter returns 1 remove packet from queue

       Packet* filter(nsaddr_t id);

       void   Terminate(void);

       Tcl_Channel tchan_;  /* place to write trace records */tchan_指向存放trace文件内容的地方

       TracedInt curq_;     /* current qlen seen by arrivals */当前的队列长度

       void trace(TracedVar*); /* routine to write trace records */实现写下trace记录的程序

private:

        int Prefer_Routing_Protocols;

/*

 * A global list of Interface Queues.  I use this list to iterate

 * over all of the queues at the end of the simulation and flush

 * their contents. - josh

 */

public:

LIST_ENTRY(PriQueue) link;

static struct PriQueue_List prhead;

};

#endif /* !_priqueue_h */

2.修改queue/ priqueue.cc

PriQueue::PriQueue() : DropTail()

{

       bind("curq_",&curq_);

       tchan_=0;

       bind("Prefer_Routing_Protocols", &Prefer_Routing_Protocols);

               LIST_INSERT_HEAD(&prhead, this, link);

}

 

int PriQueue::command(int argc, const char*const* argv)

{

 if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {

      Terminate();

     //FALL-THROUGH to give parents a chance to reset

  }

 else if(argc == 3 &&strcmp(argv[1], "attach") == 0) {

      int mode;

      const char* id = argv[2];

      Tcl& tcl = Tcl::instance();

      tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);

      if (tchan_ == 0) {

             tcl.resultf("trace: can't attach %s for writing", id);

             return (TCL_ERROR);

      }

      return (TCL_OK);

   }

 return DropTail::command(argc, argv);

}

 

void PriQueue::recv(Packet *p, Handler *h)

{

   struct hdr_cmn *ch = HDR_CMN(p);

    curq_ = q_->length();

  

       if(Prefer_Routing_Protocols) {

   ……………………………

}

}

void PriQueue::trace(TracedVar* v)

{

       char wrk[500], *p;

       if (((p = strstr(v->name(), "curq")) == NULL) ) {

               fprintf(stderr, "PriQueue:unknown trace var %s\n", v->name());

               return;

       }

strstr的功能返回curqv->name()中第一次出现的位置,如果没有返回NULLfprintf(文件指针,格式字符串,输出表列);将按格式要求处理后的数据写入文件
 

       if (tchan_) {实现从trace文件中数据读取

               int n;

               double t = Scheduler::instance().clock();将仿真时间赋给t

               if (strstr(v->name(), "curq") != NULL) {

                       sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));

               }

 

/*sprintftint(*((TracedInt*) v))按照 %g %d保存到wrk数组中,在此处实现新qlen.tr文件的输出格式,如第四步下图所示。t为当前仿真时刻,由于t的指数大于-4故按照%f格式输出。int(*((TracedInt*) v))为当前时刻的队列大小*/%g是一种输出格式,指数小于-4%e输出,否则安装%f输出;当大于精度时按%e输出,否则安装%f输出。%min.max g其中minmax指定了输出数据的精度——最小和最大有效数据字符个数。如%6g%.7g最小为6个有效字符个数,最大为7个有效字符个数。

 

               n = strlen(wrk);计算wrk中有效长度

               wrk[n] = '\n';

               wrk[n+1] = 0;

               (void)Tcl_Write(tchan_, wrk, n+1);

       }

       return;

}

3.修改tcl/lib/ns-default.tcl

加入 Queue/DropTail/PriQueue set curq_ 0然后重新编译。

4. 运行测试脚本

运行脚本后生成该脚本的trace文件,模拟时间为5秒。

 

 

 

为了方便查看,启动NS2中的gnuplot画图工具作图,具体步骤如下图所示:

 

运行tcl脚本和调用gnuplot

 

调用gnuplot,并设置相关参数,set设置坐标时要区分大小写!set xlabelset Xlabel

不同!

 

 

生成图像

 

 

 

tcl脚本程序如下:

set opt(chan)           Channel/WirelessChannel    ;# channel type

set opt(prop)           Propagation/TwoRayGround   ;# radio-propagation model

set opt(netif)          Phy/WirelessPhy            ;# network interface type

set opt(mac)            Mac/802_11                 ;# MAC type

set opt(ifq)            Queue/DropTail/PriQueue    ;# interface queue type

set opt(ll)             LL                         ;# link layer type

set opt(ant)            Antenna/OmniAntenna        ;# antenna model

set opt(ifqlen)         50                         ;# max packet in ifq

set opt(adhocRouting)   DumbAgent                  ;# routing protocol

set opt(x)          670           ;# X dimension of the topography

set opt(y)          670           ;# Y dimension of the topography

set ns [new Simulator]

#number of nodes

set num_mobile_nodes 3

 

设置数据流速率

Mac/802_11 set dataRate_  1Mb

Mac/802_11 set basicRate_  1Mb

建立trace文件——用于数据的记录

set ntr [open out_rc_3.tr w]

$ns trace-all $ntr

 

set chan  [new $opt(chan)] 信道的声明

建立拓扑结构

set topo    [new Topography]

$topo load_flatgrid $opt(x) $opt(y)

# Create God动态保存个移动节点之间的连接关系

create-god $num_mobile_nodes

 

# config node 节点信息的配置

$ns node-config -adhocRouting $opt(adhocRouting) \

                -llType  $opt(ll) \

                 -macType $opt(mac) \

                 -ifqType $opt(ifq) \

                 -ifqLen $opt(ifqlen) \

                 -antType $opt(ant) \

                 -propType $opt(prop)    \

                 -phyType $opt(netif) \

                 -channel $chan\

                 -topoInstance $topo \

                 -wiredRouting ON \

                 -agentTrace ON \

                 -routerTrace ON \

                 -macTrace ON    \

                 -movementTrace ON

 

是否启用RTS/CTS协议使用时默认为0否则为3000MAC层固定的)

Mac/802_11 set RTSThreshold_ 3000 

创建节点,物理范围

for {set i 0} {$i < $num_mobile_nodes} {incr i} {

    set wl_node_($i) [$ns node]        

    $wl_node_($i) random-motion 0               ;# disable random motion

    puts "wireless node $i created ..."

    $wl_node_($i) set X_ [expr $i * 10.0]

    $wl_node_($i) set Y_ [expr $i * 10.0]

    $wl_node_($i) set Z_ 0.0

}

以下内容是关键部分,用于实现从trace文件中读取某个节点的队列长度

设置目标节点的接口队列——确定要查看哪个节点的队列长度

set wl_ifq [$wl_node_(0) set ifq_(0)]

trace文件的内容放到queuechan

set queuechan [open qlen.tr w]

实现wl_ifqqueuechan的相结合——trace文件中获取相应节点的实时队列长度

$wl_ifq attach $queuechan

设置要观察的变量为当前队列长度curq_

$wl_ifq trace curq_

 

该程序段实现对各节点的代理和应用的定义,得到一个环形的数据流模式!

for {set i 0} {$i < $num_mobile_nodes} {incr i} {

    set src_udp_($i) [new Agent/UDP]

    $src_udp_($i) set class_ $i

    set dst_udp_($i) [new Agent/Null]

    $ns attach-agent $wl_node_($i) $src_udp_($i)

$ns attach-agent $wl_node_([expr ($i+1)%($num_mobile_nodes)]) $dst_udp_($i)

 

    set app_($i) [new Application/Traffic/CBR]

    $app_($i) set packetSize_ 1025

    $app_($i) set interval_ 0.005

    $app_($i) attach-agent $src_udp_($i)

    $ns connect $src_udp_($i) $dst_udp_($i)

    $ns set fid_ $i

    $ns at $i "$app_($i) start"

}

 

# Define node initial position in nam

for {set i 0} {$i < $num_mobile_nodes} {incr i}

{

    $ns initial_node_pos $wl_node_($i) 20

}

 

# Tell nodes when the simulation ends

for {set i 0} {$i < $num_mobile_nodes } {incr i} {

    $ns at 10.0 "$wl_node_($i) reset";

}

for {set i 0} {$i < $num_mobile_nodes} {incr i} {

    $ns at 5.0 "$app_($i) stop"

}

$ns at 11.0 "puts \"NS EXITING...\" ; $ns halt"

proc stop {} {

    global ns ntr queuechan

    close $ntr

    close $queuechan

}

$ns run