分类:
2011-02-12 22:01:25
我們要採用的方 法就是在封包的接收端去查看封包表頭內的資訊以計算出OWD、IPDV、或者是Packet Loss數量,其中最重 要的資訊就是Sending Time(傳送時間)和Sequence Number(封包序號)。Sending Time可以用來計算出OWD和IPDV,計算的方式如下:
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.h和mymeasure.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.5ms的propagation delay和封包被節點處理時間)。