NS2版本:2.34
要实现简单的路由协议: 就是按照你的要求从节点1发到节点2在从节点2发到节点3,我修改的是node节点的addr-classifier功能,因为addr-classifier是负责包的转发功能。所有的数据都是通过addr-classifier转发出去或者转发给上层协议。用port-classifier也可以实现类似功能,但是在仿真的时候不能加入数据比如ftp数据。最后还是要在addr-classifier中对数据进行处理。
以下是执行步骤:
1) 首先在route-proto.tcl添加一个路由simple 什么事情都不做。
加入办法为:
1
Class Agent/rtProto/simple -superclass Agent/rtProto
2
Agent/rtProto/simple proc init-all args { }
加入的位置大家可以观察一下其他类似的语句,那些是其他协议的句子
使用时要记得在仿真脚本加入$ns rtproto simple //这个在后面仿真的tcl文件会看到,现在不用管它
2)之后就是修改classifier的功能了。要把收到的包按照你的要求转发。
我定义新的文件为classifier-ants.h和.cc放在文件ns-2.34/classifier里
classifier-ants.h文件为:
#include
"
classifier.h
"
class
AntsClassifier :
public
Classifier {
public
:
AntsClassifier();
void
recv(Packet
*
p, Handler
*
h);
//
处理接收的报文
int
nid;
//
节点对应的编号,在ns2里节点是从0开始逐一编号的,在对应的tcl脚本有定义
};
classifier-ants.cc文件为:
#include
"
classifier.h
"
#include
"
classifier-ants.h
"
static
class
AntsClassifierClass :
public
TclClass {
public
:
AntsClassifierClass() : TclClass(
"
Classifier/Ants
"
) {}
TclObject
*
create(
int
,
const
char
*
const
*
) {
return
(
new
AntsClassifier());
}
} class_ants_classifier;
AntsClassifier::AntsClassifier() { bind(
"
tid_
"
,
&
nid);}
void
AntsClassifier::recv(Packet
*
p, Handler
*
h){
NsObject
*
node
=
NULL;
Tcl
&
tcl
=
Tcl::instance();
if
(nid
==
0
)
{
tcl.evalf(
"
[Simulator instance] get-link-head %d %d
"
,
0
,
1
);
//
[Simulator instance]获取当前实例
node
=
(NsObject
*
)TclObject::lookup(tcl.result());
//
获取链路0-1对象的指针
node
->
recv(p,h);}
if
(nid
==
1
) { tcl.evalf(
"
[Simulator instance] get-link-head %d %d
"
,
1
,
3
);
node
=
(NsObject
*
)TclObject::lookup(tcl.result());
node
->
recv(p,h); }
if
(nid
==
3
)
{
free(p);
}
}
仿真时我设置了4个节点 0,1,2,3 功能是0发给1,1发给3.
在这里tid_是相对应的节点的节点号,要从tcl获得,但是对应的classifier没有这个变量
要从node的id_获得的,所以用bind进行绑定,要注意的是节点获得id号之后id_才赋值了,
3)在这里我添在ns-node.tcl文件的
$self nodeid $id_ ;# Propagate id_ into c++ space语句之后,加入
Classifier
/
Ants
set
tid_ $id_
就能把id_的值传给tid_了,之后bind就能把tid_就能传给nid
4)在写了新的classifier功能后要记得在ns-rtmodule.tcl注册,因为修改classifier是修改module模块
加上:
RtModule
/
Ants instproc register { node } {
$self next $node
$self instvar classifier_
set
classifier_ [
new
Classifier
/
Ants]
$node install
-
entry $self $classifier_
}
5)当然还要在rtmodule.h和rtmodule.cc修改。在rtmodule.h上加上:
class
AntsRoutingModule :
public
RoutingModule {
public
:
AntsRoutingModule() : RoutingModule() {}
virtual
const
char
*
module_name()
const
{
return
"
Ants
"
; }
virtual
int
command(
int
argc,
const
char
*
const
*
argv);
protected
:
AntsClassifier
*
classifier_;
};
这一段代码的位置参照类似代码的位置添加即可
注:这里还要加上头文件
#include
"
classifier-ants.h
"
不然会出现编译错误。
6)rtmodule.cc加上
static
class
AntsRoutingModuleClass :
public
TclClass {
public
:
AntsRoutingModuleClass() : TclClass(
"
RtModule/Ants
"
) {}
TclObject
*
create(
int
,
const
char
*
const
*
) {
return
(
new
AntsRoutingModule);
}
} class_ants_routing_module;
接着加上:
int
AntsRoutingModule::command(
int
argc,
const
char
*
const
*
argv) {
Tcl
&
tcl
=
Tcl::instance();
if
(argc
==
3
) {
if
(strcmp(argv[
1
] ,
"
route-notify
"
)
==
0
) {
Node
*
node
=
(Node
*
)(TclObject::lookup(argv[
2
]));
if
(node
==
NULL) {
tcl.add_errorf(
"
Invalid node object %s
"
, argv[
2
]);
return
TCL_ERROR;
}
if
(node
!=
n_) {
tcl.add_errorf(
"
Node object %s different from n_
"
, argv[
2
]);
return
TCL_ERROR;
}
n_
->
route_notify(
this
);
return
TCL_OK;
}
if
(strcmp(argv[
1
] ,
"
unreg-route-notify
"
)
==
0
) {
Node
*
node
=
(Node
*
)(TclObject::lookup(argv[
2
]));
if
(node
==
NULL) {
tcl.add_errorf(
"
Invalid node object %s
"
, argv[
2
]);
return
TCL_ERROR;
}
if
(node
!=
n_) {
tcl.add_errorf(
"
Node object %s different from n_
"
, argv[
2
]);
return
TCL_ERROR;
}
n_
->
unreg_route_notify(
this
);
return
TCL_OK;
}
}
return
(RoutingModule::command(argc, argv));
}
以上两段代码的位置同样参照其他协议类似代码的位置
7)之后在ns-node.tcl
Node
set
module_list_ { Base }
修改为
Node
set
module_list_ { Ants }
注:这个修改完以后,除了我们现在这个使用这个协议的tcl例子可用外,其他我们原来的仿真例子均不可用了。
因此做完这个实验要把这个改回来。(很重要,我是新手,自己调试的时候郁闷死我了)
8)最后在Makefile里面的OBJ_CC加上
classifier
/
classifier
-
ants.o
附tcl脚本:
set
ns [
new
Simulator]
$ns rtproto simple
set
nf [open
out
.nam w]
$ns namtrace
-
all $nf
#Define a
'
finish
'
procedure
proc finish {} {
global
ns nf
$ns flush
-
trace
#Close the NAM trace file
close $nf
#Execute NAM on the trace file
exec nam
out
.nam
&
exit
0
}
#Create four nodes
set
n0 [$ns node]
set
n1 [$ns node]
set
n2 [$ns node]
set
n3 [$ns node]
#Create links between the nodes
$ns duplex
-
link $n0 $n1 2Mb 10ms DropTail
$ns duplex
-
link $n0 $n2 2Mb 10ms DropTail
$ns duplex
-
link $n1 $n3 2Mb 10ms DropTail
$ns duplex
-
link $n2 $n3 2Mb 10ms DropTail
set
udp [
new
Agent
/
UDP]
$ns attach
-
agent $n0 $udp
set
null
[
new
Agent
/
Null]
$ns attach
-
agent $n3 $
null
$ns connect $udp $
null
#Setup a CBR over UDP connection
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
#Schedule events
for
the CBR and FTP agents
$ns at
0.1
"
$cbr start
"
$ns at
4.5
"
$cbr stop
"
$ns at
5.0
"
finish
"
$ns run
学习ns2一定要用tcl-debug和gdb 用这2个工具能很容易解决学习上遇到的问题,对运行原理有深刻的了解cl////
注:因为我按照原文做的过程中遇到了一些小错误,我在原文的基础上已经做了更正。
原文:http://blog.sina.com.cn/s/blog_570d8e0f0100i3ic.html