2007/12/15

NS2 快速入門: DV-distance 模擬 (4)

先新增一個自訂的 Agent

之後在修改執行演算法的部份來跑自訂的 protocol

新增 Agent 的方法如下:

(附註: 這裡的 ns2 目錄是指 ns2 所在的目錄,每個人不一定一樣,
ex: ~/ns-allinone-2.33/ns-2.33)

ns2/dv-distance/dv-distance.h
[cpp]
#ifndef ns_dv_distance_h
#define ns_dv_distance_h

#include "agent.h"
#include "tclcl.h"
#include "packet.h"
#include "address.h"
#include "ip.h"

struct hdr_dv_distance {

// Header access method
static int offset_; // required by PacketHeaderManager
inline static int& offset() { return offset_; }
inline static hdr_dv_distance* access(const Packet* p) {
return (hdr_dv_distance*) p->access(offset_);
}
};

class DV_DistanceAgent : public Agent {
public:
DV_DistanceAgent();
virtual int command(int argc, const char*const* argv);
virtual void recv(Packet*, Handler*);
};

#endif // ns_dv_distance_h
[/cpp]

ns2/dv-distance/dv-distance.cc
[cpp]
#include "dv-distance.h"

int hdr_dv_distance::offset_;
static class DV_DistanceHeaderClass : public PacketHeaderClass {
public:
DV_DistanceHeaderClass() : PacketHeaderClass("PacketHeader/DV_Distance",
sizeof(hdr_dv_distance)) {
bind_offset(&hdr_dv_distance::offset_);
}
} class_dv_distancehdr;

static class DV_DistanceClass : public TclClass {
public:
DV_DistanceClass() : TclClass("Agent/DV_Distance") {}
TclObject* create(int, const char*const*) {
return (new DV_DistanceAgent());
}
} class_dv_distance;

DV_DistanceAgent::DV_DistanceAgent() : Agent(PT_DV_DISTANCE) {
//bind("packetSize_", &size_);
}

int DV_DistanceAgent::command(int argc, const char*const* argv) {
if(argc == 2) {
if(strcmp(argv[1], "start") == 0) {
// Create a new packet
Packet* pkt = allocpkt();

// Access the DV_Distance header for the new packet
hdr_dv_distance* hdr = hdr_dv_distance::access(pkt);

// Send the packet
send(pkt, 0);

// return TCL_OK, so the calling function knows that
// the command has been processed
return (TCL_OK);
}
}
return (Agent::command(argc, argv));
}

void DV_DistanceAgent::recv(Packet* pkt, Handler*) {
// Access the IP header for the received packet
hdr_ip* hdrip = hdr_ip::access(pkt);

// Access the DV_distance header for the received packet
hdr_dv_distance* hdr = hdr_dv_distance::access(pkt);

printf("Recv OK");
Packet::free(pkt);
}
[/cpp]

接著要把自訂的 Agent 加到 NS2 中

才能在 NS2 中使用

1. 修改 ns2/Makefile.in
在 OBJ_CC = 的地方加上 dv-distance/dv-distance.o
(注意:修改 Makefile 無效,Makefile 會在每次 configure 後依據 Makefile.in 產生)


2. 修改 ns2/common/packet.h 加上新的 packet type

ns 2.32 以前:
在 enum packet_t 加上 PT_DV_DISTANCE
(不能加在最後一個,PT_NTYPE 必須最後)

在 class p_info 的 public: p_info() { } 內
加上 name_[PT_DV_DISTANCE]="DV_Distance";

ns 2.33 以後:
在 static packet_t PT_NTYPE 前加上
static const packet_t PT_DV_DISTANCE = XX;
XX 為其他 packet type 沒用過的數字 (ex: 62)
(注意:一定要加在 PT_NTYPE 之前,且 PT_NTYPE 的 value 一定要最大,
否則發送 packet 時,會出現 Segmentation fault (core dumped) 無法正常運作)


在 class p_info 的 public: static void initName() { } 內
name_[PT_NTYPE]= "undefined"; 附近加上
name_[PT_DV_DISTANCE]="DV_Distance";
建議和加 PT_DV_DISTANCE 一樣
加在 name_[PT_NTYPE]= "undefined"; 之前


3. 修改 trace/cmu-trace.cc (非必要)

在 void CMUTrace::format(Packet* p, const char *why) {} 加上 case PT_DV_DISTANCE:

4. 修改 tcl/lib/ns-packet.tcl (非必要)
在 foreach prot { } 加上 DV_Distance
加這個是為了方便在模擬時
可以用下列方式寫在 tcl 內
只顯示想要觀察的 packet type

[code]remove-packet-header AODV ARP DV_Distance

# ...

set ns [new Simulator][/code]
[code]remove-all-packet-headers
add-packet-header AODV ARP DV_Distance

# ...

set ns [new Simulator][/code]

大功告成

開始編譯

1. 有改 Makefile.in 或 XXX.h 檔時
在 ns2 目錄下執行 ./configure; make clean; make depend; make

2. 只改 source code (XXX.cc 檔) 時
在 ns2 目錄下直接執行 make 就可以了

3. 只改 XXX.h 檔
如果不想等太久,可以 touch XXX.cc 後再 make
ex: touch dv-distance/dv-distance.cc; make
但不保證能正常運作

附註:若編譯時出現關於 proxytrace2any.cc 的錯誤,請參考這篇文章,以我的經驗如果是第一次編譯,2.32和2.33都會出現這個問題,可以先修改後再編譯,才不用花很久的時間重新編譯

No comments:

Post a Comment