日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何新增或修改ns2的核心模組--queue management

發布時間:2025/4/16 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何新增或修改ns2的核心模組--queue management 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?????? 原文地址 :http://140.116.72.80/~smallko/ns2/module.htm

?

這個章節最主要的目的就是希望使用者可以學會如何新增或修改ns2的核心模組,更明確的說就是去新增和修改[*.cc, *.h]檔案,以筆者和筆者朋友學習ns2的經驗來說,這需要花很多時間和很大的勇氣,時間是花來找資料,勇氣是用來承受當程式寫不好時,ns2可能隨時會當掉。不過別怕,只要跟著筆者所介紹的方法,一定可以成功,若是不成功,就寫信給筆者吧。

??????? 若是一開始就要叫ns2的新手去增加的模組,新手一定會哇哇叫,所以筆者不會這樣做,筆者先教大家拷貝ns2已經有的模組檔,但改成別的名字,這樣就可以輕鬆且很明確知道該如何增加模組。

?

<!--[if !supportLists]-->(1)??? <!--[endif]-->打開cygwin的命令視窗,把路徑切換到queue的目錄下。

cd? ns-allinone-2.27/ns-2.27/queue

?

<!--[if !supportLists]-->(2)??? <!--[endif]-->拷貝drop-tail.[cc, h]myfifo.[cc.h]

cp? drop-tail.cc? myfifo.cc

cp? drop-tail.h?? myfifo.h

?

<!--[if !supportLists]-->(3)??? <!--[endif]-->使用文字編輯軟體去修改myfifo.hmyfifo.cc(因為我們的環境是在windows下,所以建議可以使用ultra-edit來修改。

<!--[if !supportLists]-->a.?????? <!--[endif]-->先修改myfifo.h,使用取代的功能把所有DropTail改成myfifo,另外,把drop_tail改成myfifo

#ifndef ns_myfifo_h

#define ns_myfifo_h

?

#include <string.h>

#include "queue.h"

#include "config.h"

?

/*

?* A bounded, drop-tail queue

?*/

class myfifo : public Queue {

? public:

??????? myfifo() {

??????????????? q_ = new PacketQueue;

??????????????? pq_ = q_;

??????????????? bind_bool("drop_front_", &drop_front_);

??????????????? bind_bool("summarystats_", &summarystats);

??????????????? bind_bool("queue_in_bytes_", &qib_);? // boolean: q in bytes?

??????????????? bind("mean_pktsize_", &mean_pktsize_);

??????????????? //????????????? _RENAMED("drop-front_", "drop_front_");

??????? }

??????? ~myfifo() {

??????????????? delete q_;

??????? }

? protected:

??????? void reset();

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

??????? void enque(Packet*);

??????? Packet* deque();

??????? void shrink_queue(); // To shrink queue and drop excessive packets.

??????? PacketQueue *q_;??? /* underlying FIFO queue */

??????? int drop_front_;??????? /* drop-from-front (rather than from tail) */

??????? int summarystats;

??????? void print_summarystats();

??????? int qib_;?????? ????? /* bool: queue measured in bytes? */

??????? int mean_pktsize_;??? /* configured mean packet size in bytes */

};

?

#endif

?

<!--[if !supportLists]-->b.????? <!--[endif]-->再修改myfifo.cc,使用取代的功能把所有DropTail改成myfifo,另外,把drop_tail改成myfifodrop-tail改成myfifo

#include "myfifo.h"

?

static class myfifoClass : public TclClass {

?public:

??????? myfifoClass() : TclClass("Queue/myfifo") {}

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

??????????????? return (new myfifo);

??????? }

} class_myfifo;

?

void myfifo::reset()

{

??????? Queue::reset();

}

?

int myfifo::command(int argc, const char*const* argv) {

??????? if (argc==2) {

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

??????????????????????? print_summarystats();

??????????????????????? return (TCL_OK);

??????????????? }

?????????????? if (strcmp(argv[1], "shrink-queue") == 0) {

?????????????????????? shrink_queue();

?????????????????????? return (TCL_OK);

?????????????? }

??????? }

??????? if (argc == 3) {

??????????????? if (!strcmp(argv[1], "packetqueue-attach")) {

??????????????????????? delete q_;

??????????????????????? if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2])))

??????? ??????????????????????? return (TCL_ERROR);

??????????????????????? else {

??????????????????????????????? pq_ = q_;

??????????????????????????????? return (TCL_OK);

??????????????????????? }

??????????????? }

??????? }

??????? return Queue::command(argc, argv);

}

?

/*

?* drop-tail

?*/

void myfifo::enque(Packet* p)

{

??????? if (summarystats) {

??????????????? Queue::updateStats(qib_?q_->byteLength():q_->length());

??????? }

?

??????? int qlimBytes = qlim_ * mean_pktsize_;

??????? if ((!qib_ && (q_->length() + 1) >= qlim_) ||

? ??? (qib_ && (q_->byteLength() + hdr_cmn::access(p)->size()) >= qlimBytes)){

??????????????? // if the queue would overflow if we added this packet...

??????????????? if (drop_front_) { /* remove from head of queue */

??????????????????????? q_->enque(p);

??????????????????????? Packet *pp = q_->deque();

??????????????????????? drop(pp);

??????????????? } else {

??????????????????????? drop(p);

??????????????? }

??????? } else {

??????????????? q_->enque(p);

??????? }

}

?

//AG if queue size changes, we drop excessive packets...

void myfifo::shrink_queue()

{

??????? int qlimBytes = qlim_ * mean_pktsize_;

??????? if (debug_)

??????????????? printf("shrink-queue: time %5.2f qlen %d, qlim %d/n",

?????????????????????? Scheduler::instance().clock(),

??????????????????????? q_->length(), qlim_);

??????? while ((!qib_ && q_->length() > qlim_) ||

??????????? (qib_ && q_->byteLength() > qlimBytes)) {

??????????????? if (drop_front_) { /* remove from head of queue */

??????????????????????? Packet *pp = q_->deque();

??????????????????????? drop(pp);

??????????????? } else {

??????????????????????? Packet *pp = q_->tail();

????????????????? ??????q_->remove(pp);

??????????????????????? drop(pp);

??????????????? }

??????? }

}

?

Packet* myfifo::deque()

{

??????? if (summarystats && &Scheduler::instance() != NULL) {

??????????????? Queue::updateStats(qib_?q_->byteLength():q_->length());

??????? }

??????? return q_->deque();

}

?

void myfifo::print_summarystats()

{

??????? //double now = Scheduler::instance().clock();

??????? printf("True average queue: %5.3f", true_ave_);

??????? if (qib_)

??????????????? printf(" (in bytes)");

??????? printf(" time: %5.3f/n", total_time_);

}

?

<!--[if !supportLists]-->(4)??? <!--[endif]-->修改ns-default.tcl檔,設定初始內定值。

<!--[if !supportLists]-->a.?????? <!--[endif]-->cd? ns-allinone-2.27/ns-2.27/tcl/lib/

<!--[if !supportLists]-->b.????? <!--[endif]-->使用文字編輯軟體打開ns-default.tcl

<!--[if !supportLists]-->c.?????? <!--[endif]-->使用搜尋的功能找到Queue/DropTail

<!--[if !supportLists]-->d.????? <!--[endif]-->把每個初始設定值都再設一份給Queue/myfifo

……………………………………………..

?? Queue/DropTail set drop_front_ false

Queue/DropTail set summarystats_ false

Queue/DropTail set queue_in_bytes_ false

Queue/DropTail set mean_pktsize_ 500

?

Queue/myfifo set drop_front_ false

Queue/myfifo set summarystats_ false

Queue/myfifo set queue_in_bytes_ false

Queue/myfifo set mean_pktsize_ 500

……………………………………………..

?

<!--[if !supportLists]-->(5)??? <!--[endif]-->修改Makefile,把myfifo.o加入OBJ_CC內,並重新編譯。

<!--[if !supportLists]-->a.?????? <!--[endif]-->使用文字編輯軟體打開ns-allinone-2.27/ns-2.27目錄下的Makefile

<!--[if !supportLists]-->b.????? <!--[endif]-->使用搜尋找到drop-tail.o

<!--[if !supportLists]-->c.?????? <!--[endif]-->drop-tail.o後面加上queue/myfifo

……………………………………………..

tools/flowmon.o tools/loss-monitor.o /

queue/queue.o queue/drop-tail.o? queue/myfifo.o /

adc/simple-intserv-sched.o queue/red.o /

……………………………………………

<!--[if !supportLists]-->d.????? <!--[endif]-->重新編譯。

make

?

??????? 若是沒有什麼錯誤訊息產生,就是編譯成功。如下圖所示。

測試一下新安裝的模組是否可以正常的運作。可以把修改基本工具章節中的範例,把DropTail改成myfifo,試看看跑出來的結果是否跟用DropTail跑出來的一樣。

?

在這邊先做個小結,如何新增模組到ns2的核心步驟如下:

1.準備好模組檔(例如,a.cc a.h)

2.若有需要做初始設定的話,修改ns-default.tcl檔。

3.修改Makefile(a.o加到OBJ_CC)

4.重新編譯

5.測試模組

?

關於如何去寫C++的模組檔案,並不包含在這份文件內。因為每個模組的功能都不相同,但筆者可以給使用者一些建議,因為ns2內已經有很多類型的模組檔案,使用者可以根據不同的需要,找到最相近的模組檔,然後再去修改,以這樣的方式會比較容易把自己所需要的模組加入ns2的核心。

?

繼續新的主題前,筆者要告訴使用者在C++程式內非常重要的地方,第一個是bind相關函數,以前面的myfifo為例,在myfifo.h程式碼內:

class myfifo : public Queue {

? public:

??????? myfifo() {

??????????????? q_ = new PacketQueue;

??????????????? pq_ = q_;

??????????????? bind_bool("drop_front_", &drop_front_);

??????????????? bind_bool("summarystats_", &summarystats);

??????????????? bind_bool("queue_in_bytes_", &qib_);? // boolean: q in bytes?

??????????????? bind("mean_pktsize_", &mean_pktsize_);

??????????????? //????????????? _RENAMED("drop-front_", "drop_front_");

??????? }

……………………………………………..

可以看到bind或者是bind_bool,這兩個函數主要的目的是要把TCL的變數和C++的變數產生互連的關係,這樣使用者就可以在TCL檔內去設定或者去查看目前C++的變數值。(bind_bool是用在布林變數,bind是用在一般實數;而第一個參數是TCL的變數,第二個參數是C++內的變數。) 筆者以在基本工具內的範例為例,教大家如何去改變或查看C++的變數值。

?

[範例一:設定C++的參數值]

一般而言,FiFo queue的行為都是當佇列內的暫存區滿了以後,就會把新進的封包所丟棄,這是因為在ns-default.tcl初始設定檔內 drop_front_是設成false。但是如果想要改變成當暫存區滿了時候,要把佇列暫存區最前面的封包所丟棄,則可以在TCL內使用:

?

#n2n3之間的的佇列為例

set qn2n3_ [[$ns link $n2 $n3] queue]

$qn2n3_ set drop_front_ true

?

[範例二:如何去查看即時C++的參數值]

筆者以基本工具篇的範例為例,教大家如何量測FTP那條TCP flowcongestion window變化。

# 產生一個模擬的物件

set ns [new Simulator]

?

#針對不同的資料流定義不同的顏色,這是要給NAM用的

$ns color 1 Blue

$ns color 2 Red

?

#開啟一個NAM trace file

set nf [open out.nam w]

$ns namtrace-all $nf

?

#開啟一個trace file,用來記錄封包傳送的過程

set nd [open out.tr w]

$ns trace-all $nd

?

#開啟一個檔案,用來記錄TCP Flowcongestion window變化情況

set wnd_trace [open cwnd.tr w]

?

#定義一個紀錄的程序,每隔0.1秒就去查看目前TCP Flow的值

proc record {} {

global ns tcp wnd_trace

set time 0.1

??????? ?

#讀取C++cwnd_的變數值

set curr_cwnd [$tcp set cwnd_]

??? set now [$ns now]

??? puts $wnd_trace "$now?? $ curr_cwnd "

??? $ns at [expr $now+$time] "record"

}??????

?

#定義一個結束的程序

proc finish {} {

??????? global ns nf nd wnd_trace

??????? $ns flush-trace

??????? close $nf

??????? close $nd

??????? close $wnd_trace

??????? #以背景執行的方式去執行NAM

??????? #exec nam out.nam &

??????? exit 0

}

?

#產生四個網路節點

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

set n3 [$ns node]

?

#把節點連接起來

$ns duplex-link $n0 $n2 2Mb 10ms DropTail

$ns duplex-link $n1 $n2 2Mb 10ms DropTail

$ns duplex-link $n2 $n3 1.7Mb 20ms DropTail

?

set qn2n3_ [[$ns link $n2 $n3] queue]

?

#設定ns2n3之間的Queue Size10個封包大小

$ns queue-limit $n2 $n3 10

?

#設定節點的位置,這是要給NAM用的

$ns duplex-link-op $n0 $n2 orient right-down

$ns duplex-link-op $n1 $n2 orient right-up

$ns duplex-link-op $n2 $n3 orient right

?

#觀測n2n3之間queue的變化,這是要給NAM用的

$ns duplex-link-op $n2 $n3 queuePos 0.5

?

#建立一條TCP的連線

set tcp [new Agent/TCP]

$tcp set class_ 2

$ns attach-agent $n0 $tcp

set sink [new Agent/TCPSink]

$ns attach-agent $n3 $sink

$ns connect $tcp $sink

#NAM中,TCP的連線會以藍色表示

$tcp set fid_ 1

?

#TCP連線之上建立FTP應用程式

set ftp [new Application/FTP]

$ftp attach-agent $tcp

$ftp set type_ FTP

?

#建立一條UDP的連線

set udp [new Agent/UDP]

$ns attach-agent $n1 $udp

set null [new Agent/Null]

$ns attach-agent $n3 $null

$ns connect $udp $null

#NAM中,UDP的連線會以紅色表示

$udp set fid_ 2

?

#UDP連線之上建立CBR應用程式

set cbr [new Application/Traffic/CBR]

$cbr attach-agent $udp

$cbr set type_ CBR

$cbr set packet_size_ 1000

$cbr set rate_ 1mb

$cbr set random_ false

?

#設定FTPCBR資料傳送開始和結束時間

$ns at 0.1 "$cbr start"

$ns at 1.0 "$ftp start"

$ns at 1.1 "record"

$ns at 4.0 "$ftp stop"

$ns at 4.5 "$cbr stop"

?

#結束TCP的連線(不一定需要寫下面的程式碼來實際結束連線)

$ns at 4.5 "$ns detach-agent $n0 $tcp ; $ns detach-agent $n3 $sink"

?

#在模擬環境中,5秒後去呼叫finish來結束模擬(這樣要注意模擬環境中

#5秒並不一定等於實際模擬的時間

$ns at 5.0 "finish"

?

#執行模擬

$ns run

?

然後使用gnuplot,設定環境變數

set xtics 1,0.2,4

set xrange [1:4]

plot “cwnd.tr” with lines

?

第二個要注意的地方是在C++程式碼內的command程序,這個command程序可以讓TCL去呼叫C++的命令。

例如$ftp start$ftp stop中的”start””stop”都是去呼叫C++模組內的命令。所以使用者若是在寫C++模組程式時,要提供一些程序給TCL用,就可以寫在command內。

?

最後,在結束這個章節前,筆者要跟大家做個經驗的分享。在筆者使用ns2去做研究的時候,經常會去用myfifo queue去做一些量測,例如去量測封包傳送到網路的時的時間、大小、或者是統計封包被丟棄的數量,雖然這些量測都可以使用awk去分析trace file而得到,但是要提醒大家,若是要模擬的資料太大的時候,去分析的時間也會很久,但若是直接在模組內去撰寫量測的程式,模擬結束後,所需要的資料就已經可以獲得了。

?

總結

以上是生活随笔為你收集整理的如何新增或修改ns2的核心模組--queue management的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。