MFLoodルーティングプロトコル(NS-2シミュレーション)


「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

mflood.cc
#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);
	}
}

mflood-packet.h
#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

mflood-seqtable.h
#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

mflood-seqtable.cc
#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
",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 errorInfoset savedInfo $errorInfoerror "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 

その他のいくつかの設定参考書に記載されています.