在NS2中添加路由协议(1)
最近正在研究怎样把自己新写的协议添加到NS2中去,正好借鉴了一些朋友的文章,现在整理下来,以便以后参考,也希望能给广大博友一些方便。
step 1:比如我们新建的协议名字就叫做protoname,以ns2.27平台为例,我们在ns2.27目录下建立一个protoname目录。此目录包含 protoname.h,protoname.cc,protoname_pkt.h,protoname_rtable.h,protoname_rtable.cc 五个文件。
其中五个文件的具体功能和作用如下:
(1)protoname.h 定义必要的计时器和路由代理
(2)protoname.cc 执行计时器、路由代理和Tcl文件
(3)protoname_pkt.h 声明protoname路由协议需要在无线自组网节点交换的数据包
(4)protoname_rtable.h 声明我们自己的路由选择表
(5)protoname_rtable.cc 执行路由选择表
step 2:相应文件的代码
(1)protoname.h
#ifndef __protoname_h__
#define __protoname_h__
// 下面包含一些需要的头文件
#include "protoname_pkt.h" //数据包报头
#include "protoname_rtable.h"
#include <agent.h>
#include <packet.h> //数据包类
#include <trace.h> //跟踪类,用于在跟踪文件里记录输出的仿真结果
#include <timer-handler.h> //计时器基本类,创建我们自定义的计时器
#include <random.h> //随机类,用于产生伪随机数
#include <classifier-port.h> //端口分类器类,用于淘汰向上层传输的数据包
#include <mobilenode.h>
#include "arp.h"
#include "ll.h"
#include "mac.h"
#include "ip.h"
#include "delay.h"
#define CURRENT_TIME Scheduler::instance().clock() //定义了一个用于得到当前仿真时间的宏
#define JITTER (Random::uniform()*0.5) //在0-0.5之间去随机数作为发送数据的延迟时间
class Protoname; // forward declaration
class Protoname_PktTimer : public TimerHandler {
};
//定义Protoname 类
class Protoname : public Agent {
friend class Protoname_PktTimer;
//封装了自身的地址、内状态、路由表、可变的Tcl
nsaddr_t ra_addr_;
//protoname_state state_;
protoname_rtable rtable_;
int accesible_var_; //用来读取Tcl代码或脚本语言
u_int8_t seq_num_;
protected:
MobileNode* node_;
PortClassifier* dmux_; // For passing packets up to agents.端口分类器
Trace* logtarget_; // For logging.跟踪器
Protoname_PktTimer pkt_timer_; // Timer for sending packets.自定义计时器
//内部属性
inline nsaddr_t& ra_addr() { return ra_addr_; }
//inline protoname_state& state() { return state_; }
inline int& accessible_var() { return accesible_var_; }
void forward_data(Packet*); //数据包被正确传输的目的地
void recv_protoname_pkt(Packet*);
void send_protoname_pkt();
void reset_protoname_pkt_timer();
public:
Protoname(nsaddr_t);
int command(int, const char*const*);
void recv(Packet*, Handler*);
//void mac_failed(Packet*);
};
#endif
在NS2中添加路由协议(整理版)2
(2)protoname.cc
#include "protoname.h"
#include "protoname_pkt.h"
#include <random.h>
#include <cmu-trace.h>
#include <iostream>
int hdr_protoname_pkt::offset_;
static class ProtonameHeaderClass : public PacketHeaderClass {
} class_rtProtoProtoname_hdr;
static class ProtonameClass : public TclClass {
} class_rtProtoProtoname;
void
Protoname_PktTimer::expire(Event* e) {
}
Protoname::Protoname(nsaddr_t id) : Agent(PT_PROTONAME), pkt_timer_(this) {
}
int
Protoname::command(int argc, const char*const* argv) {
}
void
Protoname::recv(Packet* p, Handler* h) {
}
void
Protoname::recv_protoname_pkt(Packet* p) {
}
void
Protoname::send_protoname_pkt() {
}
void
Protoname::reset_protoname_pkt_timer() {
}
void
Protoname::forward_data(Packet* p) {
}
(3)protoname_pkt.h
#ifndef __protoname_pkt_h__
#define __protoname_pkt_h__
#include <packet.h>
#define HDR_PROTONAME_PKT(p) hdr_protoname_pkt::access(p)
struct hdr_protoname_pkt {
};
#endif
(4)protoname_rtable.h
#ifndef __protoname_rtable_h__
#define __protoname_rtable_h__
#include <trace.h>
#include <map>
typedef std::map<nsaddr_t, nsaddr_t> rtable_t;
class protoname_rtable {
};
#endif
(5)protoname_rtable.cc
#include "protoname_rtable.h"
#include "ip.h"
protoname_rtable::protoname_rtable() { }
void
protoname_rtable::print(Trace* out) {
}
void
protoname_rtable::clear() {
}
void
protoname_rtable::rm_entry(nsaddr_t dest) {
}
void
protoname_rtable::add_entry(nsaddr_t dest, nsaddr_t next) {
}
nsaddr_t
protoname_rtable::lookup(nsaddr_t dest) {
}
u_int32_t
protoname_rtable::size() {
}
在NS2中添加路由协议(整理版)3
step 3:我们需要对ns2中的一些文件进行修改,来使这个协议在tcl中被调用,
需要修改的文件有以下几个,你可以在ns目录下找到它们:
Common/packet.h
Trace/cmu-trace.h
Trace/cmu-trace.cc
Tcl/lib/ns-packet.tcl
Tcl/lib/ns-default.tcl
Tcl/lib/ns-lib.tcl
Queue/priqueue.cc
Makefile
step4:需要修改的具体内容(在需要修改的地方添加红色的字)
1.Common/packet.h (两个需要修改的地方)
1: enum packet_t {
2: PT_TCP,
3: PT_UDP,
4: PT_CBR,
5:
6: PT_PROTONAME,
7: PT_NTYPE // This MUST be the LAST one
8: };
=======================================
1: p_info() {
2: name_[PT_TCP]= "tcp";
3: name_[PT_UDP]= "udp";
4: name_[PT_CBR]= "cbr";
5:
6: name_[PT_PROTONAME]= "protoname";
7: }
2.Trace/cmu-trace.h (一个)
1: class CMUTrace : public Trace {
2:
3: private:
4:
5: void format_aodv(Packet *p, int offset);
6: void format_protoname(Packet *p, int offset);
7: };
3.Trace/cmu-trace.cc (三个,先在最上面加头文件,在找一个合适的地方加函数)
1: #include <protoname/protoname_pkt.h>
2:
3:
4:
5: void
6: CMUTrace::format_protoname(Packet *p, int offset)
7: {
8: struct hdr_protoname_pkt* ph = HDR_PROTONAME_PKT(p);
9:
10: if (pt_->tagged()) {
11: sprintf(pt_->buffer() + offset,
12: "-protoname:o %d -protoname:s %d -protoname:l %d ",
13: ph->pkt_src(),
14: ph->pkt_seq_num(),
15: ph->pkt_len());
16: }
17: else if (newtrace_) {
18: sprintf(pt_->buffer() + offset,
19: "-P protoname -Po %d -Ps %d -Pl %d ",
20: ph->pkt_src(),
21: ph->pkt_seq_num(),
22: ph->pkt_len());
23: }
24: else {
25: sprintf(pt_->buffer() + offset,
26: "[protoname %d %d %d] ",
27: ph->pkt_src(),
28: ph->pkt_seq_num(),
29: ph->pkt_len());
30: }
31: }
=========================================
1: void
2: CMUTrace::format(Packet* p, const char *why)
3: {
4:
5: case PT_PING:
6: break;
7:
8: case PT_PROTONAME:
9: format_protoname(p, offset);
10: break;
11:
12: default:
13:
14: }
4.Tcl/lib/ns-packet.tcl(一个)
1: foreach prot {
2: Protoname
3: AODV
4: ARP
5: # ...
6: NV
7: } {
8: add-packet-header $prot
9: }
5.Tcl/lib/ns-default.tcl(一个)
1: # ...
2: # Defaults defined for Protoname
3: Agent/Protoname set accessible_var_ true
6.Tcl/lib/ns-lib.tcl(两个)
1: Simulator instproc create-wireless-node args {
2: # ...
3: switch -exact $routingAgent_ {
4: Protoname {
5: set ragent [$self create-protoname-agent $node]
6: }
7: # ...
8: }
9: # ...
10: }
=======================================
1: Simulator instproc create-protoname-agent { node } {
2: # Create Protoname routing agent
3: set ragent [new Agent/Protoname [$node node-addr]]
4: $self at 0.0 "$ragent start"
5: $node set ragent_ $ragent
6: return $ragent
7: }
7.Queue/priqueue.cc(一个)
1: void
2: PriQueue::recv(Packet *p, Handler *h)
3: {
4: struct hdr_cmn *ch = HDR_CMN(p);
5:
6: if (Prefer_Routing_Protocols) {
7:
8: switch(ch->ptype()) {
9: case PT_DSR:
10: case PT_MESSAGE:
11: case PT_TORA:
12: case PT_AODV:
13: case PT_PROTONAME:
14: recvHighPriority(p, h);
15: break;
16:
17: default:
18: Queue::recv(p, h);
19: }
20: }
21: else {
22: Queue::recv(p, h);
23: }
24: }
8.Makefile(一个)
1: OBJ_CC = \
2: tools/random.o tools/rng.o tools/ranvar.o common/misc.o common/timer-handler.o \
3: # ...
4: protoname/protoname.o protoname/protoname_rtable.o \
5: # ...
6: $(OBJ_STL)
step 5:编译
在ns目录下输入下名命令进行编译:
$ make clean
$ touch common/packet.cc
$ make
到这里,我们添加新协议的过程就结束了。
step 6:测试
协议写完了,要用一个tcl对它进行测试,下面这是个很简单的而且可用的例子
set ns [new Simulator]
$ns node-config -Routing protoname
set nf [open out.nam w]
$ns namtrace-all $nf
set nd [open out.tr w]
$ns trace-all $nd
for {set i 0} {$i < 7} {incr i} {set n($i) [$ns node] }
for {set i 0} {$i < 7} {incr i} {
$ns duplex-link $n($i) $n([expr ($i+1)%7]) 1Mb 10ms DropTail
}
set udp0 [new Agent/UDP]
$ns attach-agent $n(0) $udp0
set cbr0 [new Application/Traffic/CBR]
$cbr0 set packetSize_ 500
$cbr0 set interval_ 0.005
$cbr0 attach-agent $udp0
set null0 [new Agent/Null]
$ns attach-agent $n(3) $null0
$ns connect $udp0 $null0
$ns at 0.5 "$cbr0 start"
$ns rtmodel-at 1.0 down $n(1) $n(2)
$ns rtmodel-at 2.0 up $n(1) $n(2)
$ns at 4.5 "$cbr0 stop"
$ns at 5.0 "finish"
$ns run
参考文献:
[1]Implementing a New Manet Unicast Routing Protocol in NS2,Francisco J. Ros
[2]http://ourlab.blog.sohu.com/64266258.html
转自:http://blog.163.com/kong_qing_yun/blog/static/162458006201061274147977