《NS与网络模拟》上面的代码,经过调试和修改,增加了一部分。
mflood.h
#ifndef ns_mflood_h
#define ns_mflood_h
#include <sys/types.h>
#include <cmu-trace.h>
#include <priqueue.h>
#include "mflood-seqtable.h"
//#define NOW (Scheduler::instance().clock())
#define NETWORK_DIAMETER 30
#define FORWARD_DELAY 0.01
#define NO_DELAY -1.0
class MFlood:public Agent {
friend class MFlood_RTEntry;
public:
MFlood(nsaddr_t id);
void recv(Packet *p,Handler *);
protected:
int command (int,const char *const *);
inline int initialized(){return 1&&target_;}
void rt_resolve(Packet *p);
void forward(MFlood_RTEntry *rt,Packet *p,double delay);
nsaddr_t index_;
MFlood_RTable rtable_;
Trace *logtarget;
NsObject *uptarget_;
NsObject *port_dmux_ ;
private:
u_int32_t myseq_;
};
#endif
#include "mflood.h"
#include "mflood-packet.h"
#include <cmu-trace.h>
#include <random.h>
int hdr_mflood::offset_;
static class MFloodHeaderClass:public PacketHeaderClass {
public:
MFloodHeaderClass():PacketHeaderClass("PacketHeader/MFlood",sizeof(hdr_mflood)) {
bind_offset(&hdr_mflood::offset_);
}
}class_mfloodhdr;
static class MFloodClass:public TclClass{
public:
MFloodClass():TclClass("Agent/MFlood"){}
TclObject *create(int argc,const char *const *argv) {
assert(argc==5);
return (new MFlood((nsaddr_t)atoi(argv[4])));
}
}class_rtProtoMFlood;
int MFlood::command(int argc,const char *const *argv) {
Tcl &tcl = Tcl::instance();
if(argc==2) {
if(strncasecmp(argv[1],"id",2)==0) {
tcl.resultf("%d",index_);
return TCL_OK;
}
else if (strcmp(argv[1],"uptarget")==0) {
if(uptarget_ !=0)
tcl.result(uptarget_->name());
return (TCL_OK);
}
/*else if(strcmp(argv[1],"port-dmux")==0) {
return (TCL_OK);
}*/
}else if(argc==3) {
if(strcmp(argv[1],"index_")==0){
index_ = atoi(argv[2]);
return (TCL_OK);
}else if (strcmp(argv[1],"log-target")==0 || strcmp(argv[1],"tracetarget")==0) {
logtarget = (Trace*)TclObject::lookup(argv[2]);
if(logtarget==0)
return TCL_ERROR;
return TCL_OK;
}
else if (strcmp(argv[1],"uptarget")==0) {
if(*argv[2]=='0'){
target_=0;
return (TCL_OK);
}
uptarget_ =(NsObject*)TclObject::lookup(argv[2]);
if(uptarget_==0){
tcl.resultf("no such object %s",argv[2]);
return (TCL_ERROR);
}
return (TCL_OK);
}
else if(strcasecmp(argv[1],"port-dmux")==0) {
TclObject *obj;
port_dmux_ = (NsObject *)obj;
return (TCL_OK);
}
}
return Agent::command(argc,argv);
}
MFlood::MFlood(nsaddr_t id):Agent(PT_MFlood),port_dmux_(0){
index_ = id;
logtarget = 0;
myseq_ = 0;
}
// Route Handling Functions
void MFlood::rt_resolve(Packet *p) {
//struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_mflood *fh = HDR_MFLOOD(p);
MFlood_RTEntry *rt ;
rt = rtable_.rt_lookup(ih->saddr());
if(rt==NULL) {
rt = new MFlood_RTEntry(ih->saddr(),fh->seq_);
LIST_INSERT_HEAD(&rtable_.rthead,rt,rt_link);
forward(rt,p,FORWARD_DELAY);
}
else if(rt->isNewSeq(fh->seq_))
{
forward(rt,p,FORWARD_DELAY);
rt->addSeq(fh->seq_);
}
else {
drop(p,"LOWSEQ");
}
}
void MFlood::recv(Packet *p,Handler *) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih =HDR_IP(p);
struct hdr_mflood *fh=HDR_MFLOOD(p);
assert(initialized());
if((ih->saddr()==index_) &&(ch->num_forwards()==0)) {
ch->size() += IP_HDR_LEN;
ih->ttl_ = NETWORK_DIAMETER;
fh->seq_ = myseq_++;
forward((MFlood_RTEntry*)1,p,0);
return ;
}
else if (ih->saddr() == index_) {
drop(p,DROP_RTR_ROUTE_LOOP);
return ;
}
else {
if(--ih->ttl_==0){
drop(p,DROP_RTR_TTL);
return ;
}
}
rt_resolve(p);
}
void MFlood::forward(MFlood_RTEntry *rt,Packet *p,double delay) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
assert(ih->ttl_ > 0);
assert(rt!=0);
ch->next_hop_ = -1;
ch->addr_type() = NS_AF_INET;
ch ->direction() = hdr_cmn::DOWN;
if(delay > 0.0) {
Scheduler::instance().schedule(target_,p,Random::uniform(delay*2));
}
else {
Scheduler::instance().schedule(target_,p,0);
}
}
#ifndef mflood_packet_h
#define mflood_packet_h
#define HDR_MFLOOD(p) ((struct hdr_mflood*)hdr_mflood::access(p))
struct hdr_mflood {
u_int32_t seq_;
static int offset_;
inline static int& offset() {
return offset_;
}
inline static hdr_mflood *access(const Packet *p) {
return (hdr_mflood*)p->access(offset_);
}
};
#endif
#ifndef mflood_seqtable_h
#define mflood_seqtable_h
#include <assert.h>
#include <sys/types.h>
#include <config.h>
#include <lib/bsd-list.h>
#include <scheduler.h>
//#define INFINITY 0xff
#define RTF_DOWN 0
#define RTF_UP 1
#define REM_SEQ_COUNT 1000
//Route Table Entry
class MFlood_RTEntry {
friend class MFlood_RTable;
friend class MFlood;
public:
MFlood_RTEntry();
MFlood_RTEntry(nsaddr_t src,u_int32_t seq);
bool isNewSeq(u_int32_t seq);
void addSeq(u_int32_t seq);
protected:
LIST_ENTRY(MFlood_RTEntry) rt_link;
nsaddr_t src_;
u_int32_t rt_seqnos[REM_SEQ_COUNT];
u_int32_t max_seqno;
u_int32_t min_seqno;
u_int16_t seq_it; // seqno's iterator
};
// The Routing Table
class MFlood_RTable {
friend class MFlood;
public:
MFlood_RTable() {LIST_INIT(&rthead);} // initial the routing table
void rt_delete(nsaddr_t id);
MFlood_RTEntry *rt_lookup(nsaddr_t id);
void rt_print();
private:
LIST_HEAD(,MFlood_RTEntry) rthead;
};
#endif
#include "mflood-seqtable.h"
MFlood_RTEntry::MFlood_RTEntry() {
src_= 0;
for(int i=0; i<REM_SEQ_COUNT; i++)
rt_seqnos[i] = 0xffffffff;
max_seqno = 0;
min_seqno = 0;
seq_it = 0;
}
// The routing table
MFlood_RTEntry::MFlood_RTEntry(nsaddr_t src,u_int32_t seq){
src_ = src;
for(int i=0; i < REM_SEQ_COUNT;i++)
rt_seqnos[i] = 0xffffffff;
rt_seqnos[0] = seq;
max_seqno = seq ;
min_seqno = 0;
seq_it = 1;
}
bool MFlood_RTEntry::isNewSeq(u_int32_t seq) {
if(seq > max_seqno)
return true;
// 抛弃太久以前的数据包
if(seq < min_seqno)
return false;
for(int i=0;i<REM_SEQ_COUNT;i++)
if(seq == rt_seqnos[i])
return false;
return true ;
}
void MFlood_RTEntry::addSeq(u_int32_t seq) {
//u_int16_t min_it = 0;
if(seq < min_seqno)
return ;
if(seq > max_seqno)
max_seqno = seq;
rt_seqnos[seq_it++] = seq;
seq_it %= REM_SEQ_COUNT;
min_seqno = 0xffffffff;
for(int i=0 ; i < REM_SEQ_COUNT ; i++)
if(min_seqno > rt_seqnos[i])
min_seqno = rt_seqnos[i];
}
MFlood_RTEntry *MFlood_RTable::rt_lookup(nsaddr_t id){
MFlood_RTEntry *rt = rthead.lh_first;
for(;rt; rt = rt->rt_link.le_next)
{
if(rt->src_ == id)
break ;
}
return rt;
}
void MFlood_RTable::rt_delete(nsaddr_t id) {
MFlood_RTEntry *rt = rt_lookup(id);
if(rt){
LIST_REMOVE(rt,rt_link);
delete rt;
}
}
void MFlood_RTable::rt_print() {
MFlood_RTEntry *rt = rthead.lh_first;
for(;rt;rt=rt->rt_link.le_next) {
// printf("index:%d,seq:%d\n",rt->src_,rt->max_seqno);
}
return ;
}
编译出现过的错误:
INITIALIZE THE LIST xListHead
(_o17 cmd line 1)
invoked from within
"_o17 cmd port-dmux _o26"
invoked from within
"catch "$self cmd $args" ret"
invoked from within
"if [catch "$self cmd $args" ret] {
set cls [$self info class]
global errorInfo
set savedInfo $errorInfo
error "error when calling class $cls: $args" $..."
(procedure "_o17" line 2)
(SplitObject unknown line 2)
invoked from within
"$agent port-dmux $dmux_"
(procedure "_o14" line 11)
(Node/MobileNode add-target-rtagent line 11)
invoked from within
"$self add-target-rtagent $agent $port"
(procedure "_o14" line 28)
(Node/MobileNode add-target line 28)
invoked from within
"$self add-target $agent $port"
(procedure "_o14" line 15)
(Node attach line 15)
invoked from within
"$node attach $ragent [Node set rtagent_port_]"
(procedure "_o3" line 84)
(Simulator create-wireless-node line 84)
invoked from within
"_o3 create-wireless-node"
("eval" body line 1)
invoked from within
"eval $self create-wireless-node $args"
(procedure "_o3" line 23)
(Simulator node line 23)
invoked from within
"$ns_ node"
("for" body line 3)
invoked from within
"for {set i 0} {$i<$val(nn)} {incr i} {
puts "here 1"
set nodes($i) [$ns_ node]
puts "here 2"
#$nodes($i) random-motion
}"
(file "mflood/test_mflood.tcl" line 40)
num_nodes is set 3
在原mflood.cc文件中增加一段代码。
mflood路由协议的tcl测试脚本
#parameters
set val(ifqlen) 50
set val(nn) 3
set val(rp) MFlood
set val(chan) Channel/WirelessChannel
set val(prop) Propagation/TwoRayGround
set val(netif) Phy/WirelessPhy
set val(mac) Mac/802_11
set val(ifq) Queue/DropTail/PriQueue
set val(ll) LL
set val(ant) Antenna/OmniAntenna
set val(stop) 200
set ns_ [new Simulator]
set tracefd [open mflood.tr w]
$ns_ trace-all $tracefd
# topology
set topo [new Topography]
$topo load_flatgrid 1000 500
create-god $val(nn)
set channel [new Channel/WirelessChannel]
$ns_ node-config -adhocRouting $val(rp) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen)) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-channel $channel \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace OFF \
-movementTrace ON
for {set i 0 } { $i < $val(nn)} { incr i} {
set nodes($i) [$ns_ node]
$nodes($i) random-motion 0
}
$nodes(0) set X_ 100.0
$nodes(0) set Y_ 200.0
$nodes(0) set Z_ 0.0
$nodes(1) set X_ 250.0
$nodes(1) set Y_ 200.0
$nodes(1) set X_ 0.0
$nodes(2) set X_ 400.0
$nodes(2) set Y_ 200.0
$nodes(2) set Z_ 0.0
set udp_(0) [new Agent/UDP]
$ns_ attach-agent $nodes(0) $udp_(0)
set null_(0) [new Agent/Null]
$ns_ attach-agent $nodes(2) $null_(0)
$ns_ connect $udp_(0) $null_(0)
set cbr_(0) [new Application/Traffic/CBR]
$cbr_(0) set packetSize_ 512
$cbr_(0) set interval_ 4.0
$cbr_(0) set random_ 1
$cbr_(0) set maxpkts 1000
$cbr_(0) attach-agent $udp_(0)
$ns_ at 10.0 "$cbr_(0) start"
for {set i 0} { $i < $val(nn)} {incr i} {
$ns_ at $val(stop) "$nodes($i) reset"
}
$ns_ at $val(stop) "stop"
$ns_ at $val(stop) "puts \"NS EXISTING...\";$ns_ halt"
proc stop {} {
global ns_ tracefd
$ns_ flush-trace
close $tracefd
}
puts "Starting Simulation"
$ns_ run
其他的一些设置参考书上的。