Chinaunix首页 | 论坛 | 博客
  • 博客访问: 556286
  • 博文数量: 126
  • 博客积分: 2071
  • 博客等级: 大尉
  • 技术积分: 1522
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-24 16:09
文章分类
文章存档

2013年(8)

2012年(37)

2011年(80)

2010年(1)

分类:

2011-02-12 22:01:25

在本小節中,筆者將介紹如何在ns2核心中直接新增模組,以用來量測以UDP為傳輸協定的應用程式之One Way Delay (OWD)IP Delay Variance (IPDV,或是Jitter)Packet Loss數量。使用這個 方法的好處就是當模擬結束後,所需要的數據就直接存放到檔案內,然後就可以直接進行分析。

        我們要採用的方 法就是在封包的接收端去查看封包表頭內的資訊以計算出OWDIPDV、或者是Packet Loss數量,其中最重 要的資訊就是Sending Time(傳送時間)Sequence Number(封包序號)Sending Time可以用來計算出OWDIPDV,計算的方式如下:

 

One Way Delay = 接收時間 傳送時間

IPDV = |目前量測到的OWD 上一次量測到的OWD |

 

        Packet Loss數量則可以由封包序號的不連續性所計算出,每一個封包在傳送端發送前,傳送端都會給封包一個序號,序號是連續性 的,因此若是在接收到發現序號有不連續的發生,則可視為有封包的移失(這邊不考慮Out-of-Order情況)

       

[方法]

1.      NS2中,在RTP表頭中已經有序號的欄位。目前第 一步要做的就是去增加一個Sending Time的欄位,並且當封 包在傳送端發送時,把發送時間紀錄到此欄位內。

 

1.1    新增欄位sendtime_packet common header (修改common/packet.h)

struct hdr_cmn {

        enum dir_t { DOWN= -1, NONE= 0, UP= 1 };

        packet_t ptype_;      // packet type (see above)

        int     size_;                // simulated packet size

        int     uid_;         // unique id

        int     error_;              // error flag

        int     errbitcnt_;     // # of corrupted bits jahn

        int     fecsize_;

        double      ts_;           // timestamp: for q-delay measurement

        int     iface_;              // receiving interface (label)

        dir_t direction_;        // direction: 0=none, 1=up, -1=down

        double  sendtime_;  // 新增的sendtime_欄位

        ...

        ...

        ...

        inline int& addr_type() { return (addr_type_); }

        inline int& num_forwards() { return (num_forwards_); }

        inline int& opt_num_forwards() { return (opt_num_forwards_); }

        //monarch_end

        inline double& sendtime() { return (sendtime_); } // added by smallko

   }

 

1.1    udp要傳送封包出去時,把現在時間加入到sendtime這個欄位。(修改apps/udp.cc)

void UdpAgent::sendmsg(int nbytes, AppData* data, const char* flags)

   {

    ...

    ...

    ...

    double local_time = Scheduler::instance().clock();

        while (n-- > 0) {

                p = allocpkt();

                hdr_cmn::access(p)->size() = size_;

                hdr_rtp* rh = hdr_rtp::access(p);

                rh->flags() = 0;

                rh->seqno() = ++seqno_;

                hdr_cmn::access(p)->timestamp() =

                    (u_int32_t)(SAMPLERATE*local_time);

                hdr_cmn::access(p)->sendtime_ = local_time;   //把現在時間加入到sendtime這個欄位

                // add "beginning of talkspurt" labels (tcl/ex/test-rcvr.tcl)

                if (flags && (0 ==strcmp(flags, "NEW_BURST")))

                        rh->flags() |= RTP_M;

                p->setdata(data);

                target_->recv(p);

        }

        n = nbytes % size_;

        if (n > 0) {

                p = allocpkt();

                hdr_cmn::access(p)->size() = n;

                hdr_rtp* rh = hdr_rtp::access(p);

                rh->flags() = 0;

                rh->seqno() = ++seqno_;

                hdr_cmn::access(p)->timestamp() =

                    (u_int32_t)(SAMPLERATE*local_time);

                hdr_cmn::access(p)->sendtime_ = local_time;   //把現在時間加入到sendtime這個欄位

                // add "beginning of talkspurt" labels (tcl/ex/test-rcvr.tcl)

                if (flags && (0 == strcmp(flags, "NEW_BURST")))

                        rh->flags() |= RTP_M;

                p->setdata(data);

                target_->recv(p);

        }

        idle();

}  

 

2.      tools的目錄內,新增mymeasure.hmymeasure.cc

[mymeasure.h內容]

#include

#include

#include "agent.h"

#include "config.h"

#include "packet.h"

#include "ip.h"

#include "rtp.h"

 

class mymeasure : public Agent {

public:

        mymeasure();

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

        virtual void recv(Packet* pkt, Handler*);

protected:

        int nlost_;       //移失封包數量

        int npkts_;             //接收到的封包數量

        int expected_;

        int bytes_;      //接收到的封包總長度(bytes)

        int seqno_;             //封包序號

        double last_packet_time_; //上一次封包接收時間

       

        char buf[100];

        FILE *pFile;          

        double now;

        double sum_ipdv_;     //jitter總和,可以用來算average jitter

        double sum_owd_;      //one way delay總和,可以用來算average owd            

        double current_owd_;  //目前所量測到的one way delay

        double current_ipdv_; //目前所量測到的jitter

        double min_owd_;      //最小的one way delay

        double previous_owd_; //上一次量測到的one way delay

};

 

[mymeasure.cc內容]

#include

#include "agent.h"

#include "config.h"

#include "packet.h"

#include "ip.h"

#include "rtp.h"

#include "mymeasure.h"

 

static class mymeasureClass : public TclClass {

public:

        mymeasureClass() : TclClass("Agent/mymeasure") {}

        TclObject* create(int, const char*const*) {

                return (new mymeasure());

        }

} class_mymeasure;

 

mymeasure::mymeasure() : Agent(PT_NTYPE)

{

        bytes_ = 0;

        nlost_ = 0;

        npkts_ = 0;

        expected_ = -1;

        last_packet_time_ = 0.;

        seqno_ = 0;

       

        sum_ipdv_                 = 0;             

        sum_owd_                    = 0;     

        current_owd_             = 0;     

        current_ipdv_             = 0;     

        previous_owd_           = 0;

        min_owd_                  = 100000000;

       

        bind("nlost_", &nlost_);

        bind("npkts_", &npkts_);

        bind("bytes_", &bytes_);

        bind("lastPktTime_", &last_packet_time_);

        bind("expected_", &expected_);

}

 

void mymeasure::recv(Packet* pkt, Handler*)

{

        hdr_rtp* p = hdr_rtp::access(pkt);

        seqno_ = p->seqno();

        bytes_ += hdr_cmn::access(pkt)->size();

        ++npkts_;

       

        now=Scheduler::instance().clock();

       

        //計算One Way Delay

        current_owd_=(Scheduler::instance().clock()-hdr_cmn::access(pkt)->sendtime_);

       

        //看看量測到 的owd是否 是最小值

        if (current_owd_

                min_owd_ = current_owd_;

       

        sum_owd_+=current_owd_;     // one way delay總和,可以用來算average owd

       

        if (previous_owd_!=0)      {   // Jitter: ipdv=|current_owd_-previous_owd_|

                if (previous_owd_

                        current_ipdv_=(current_owd_-previous_owd_);

                else

                        current_ipdv_=(previous_owd_-current_owd_);

               

                sum_ipdv_+=current_ipdv_; // ipdv總和,可以用來算average ipdv (Jitter)

        }

        previous_owd_=current_owd_;

       

        //在這裡,只把one way delay的資訊寫到檔 案內.若是有 不同的需要,可 以參照下面這行程式

        //把所需的資 料寫到檔案

        fprintf(pFile, "%0.1f %0.1f\n", now * 1000, current_owd_ * 1000);

               

        //檢查封包是 否有移失

        if (expected_ >= 0) {

                //從封包序號的不連續性,就可以得知是否有封包移失

                int loss = seqno_ - expected_;

                if (loss > 0) {

                        nlost_ += loss;

                        Tcl::instance().evalf("%s log-loss", name());

                }

        }

        last_packet_time_ = Scheduler::instance().clock();

        expected_ = seqno_ + 1;

        Packet::free(pkt);

}

 

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

{

        if (strcmp(argv[1], "clear") == 0) {

                expected_ = -1;

                return (TCL_OK);

        }

       

        //設定檔名

        if (strcmp(argv[1], "set_filename") == 0) {

                strcpy(buf, argv[2]);

                pFile = fopen(buf, "w");

                return (TCL_OK);

        } 

       

        //關閉檔案

        if (strcmp(argv[1], "close_file") == 0) {

                fclose(pFile);

                return (TCL_OK);

        } 

       

        return (Agent::command(argc, argv));

}

 

3. 修改ns-default.tcl檔,把下面的程式碼加入。

Agent/mymeasure set nlost_ 0

Agent/mymeasure set npkts_ 0

Agent/mymeasure set bytes_ 0

Agent/mymeasure set lastPktTime_ 0

Agent/mymeasure set expected_ 0

 

4. Makefile內把tools/mymeasure.o加入OBJ_CC內。

5. 重新Make

6. 測試。下面的程式碼是用來測試One Way Delay

set ns [new Simulator]

 

set testTime   85.0

 

set s [$ns node]

set d [$ns node]

 

$ns duplex-link $s $d 10Mb 5.5ms DropTail

 

set udp [new Agent/UDP]

$ns attach-agent $s $udp

set cbr [new Application/Traffic/CBR]

$cbr attach-agent $udp

$cbr set packet_size_ 1000

$udp set packetSize_ 1000

$cbr set rate_ 1000000

set null [new Agent/mymeasure]

$ns attach-agent $d $null

$ns connect $udp $null

$null set_filename owd_flow0

 

proc finish {} {

    global ns

    exit 0

}

 

$ns at 0.0 "$cbr start"

$ns at $testTime "$cbr stop"

$ns at $testTime "$null close_file"

$ns at [expr $testTime + 1.0] "finish"

 

$ns run

 

執行結束後,會產生一個檔案owd_flow0,裡面紀錄了每封包的one-way-delay

6.3 6.3

14.3 6.3

22.3 6.3

30.3 6.3

38.3 6.3

46.3 6.3

54.3 6.3

62.3 6.3

70.3 6.3

78.3 6.3

……

……

……

由於測試的程式是CBR,所以所有的數據都是6.3ms(包含了5.5mspropagation delay和封包被節點處理時間)

阅读(1868) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~