opnet的flood泛洪路由实现

NS2的有一个入门级的无线网络MFLood例子,可以很好的学习NS的一些基本的功能。很可惜,opnet没有,所以在学习opnet的过程中,做了下面这个基于有线网络的flood工程,分享出来,欢迎下载测试,提意见,改进,分享!

下载地址:http://download.csdn.net/detail/yanhc519/6584655

网络层如下,一个3x4的简单的有线网络

opnet的flood泛洪路由实现_第1张图片

需要说明的是无线网络一般需要处理同步的问题,即周边节点收到泛洪包后,需要各自错开发送,实现时通过随机延时实现,因为如果周边节点收到泛洪包后同时发送会造成无线包的碰撞(刚看了一下NS的MFLood里自己产生的包会马上发送,转发的包会随机延时Random::uniform(0.01*2),自己实现的有线网络flood时候,所有的都对齐了)。

对于有线网络没有碰撞的问题,但需要实现slotted,就像slotted aloha一样,因为如果不是slotted:

假设节点5是源,那么节点6、9会同时收到包,然后同时发送给节点10,但是由于opnet的离散时间仿真机制,经同时收到了节点6、9的包,但节点10是按顺序处理6、9发来的包的,假设6发来的包事件先响应,那么根据flood原理,会往6转发包,而这是不应该的,造成泛洪的开销变大。

通过采用slotted packet system可以解决这个问题。这个在介绍process时会看到。

节点层通过module的摆放,可以反映分层的思想,application,network,link层。

opnet的flood泛洪路由实现_第2张图片

对于process层,采用了slotted packet system


ARV表示接收到了自己节点app产生的包,设置源地址和序号,然后插入subq(由于时隙系统,需要引入队列机制)。

RCV表示接收到了其它节点的包,需要提取源地址和序号,进行泛洪路由的处理机制。仿照了Mflood的流程:

如果源地址不存在路由表中,新建一个新的路由表项,并初始化序号和流号,将包插入subq。

如果存在源地址路由表项,序号是新的,那么添加新的序号,初始化流号,将包插入subq。

如果存在源地址路由表项,序号也是旧的,更新流号,丢弃包。

SRV表示slotted系统响应时间到了:

       读取subq的包,获取源地址和序号:

                 如果是自己的地址,发往所有link;

                 否则,从路由表中获取流号,发往其他link。

包定义如下图,只包含源地址和序号。


路由表定义:

// routing table entry definition
typedef struct{
	int seq_number;
	int in_strm[4];	//1 means in, 0 means no in
}structseq;

typedef struct{
	int srcaddr;
	structseq seq_num[MAX_SEQ];
	int seq_it;	// iterator
}rttable_entry;
其中in_strm用于记录 源地址-序号对应包从那个流号的链路收到。路由表采用opnet自带的链表实现。

下面是代码罗列:

SV

opnet的flood泛洪路由实现_第3张图片


HB

#define		APP_STRM	4
#define		ARV		(op_intrpt_type()==OPC_INTRPT_STRM && \
						op_intrpt_strm()==APP_STRM)
#define		RCV		(op_intrpt_type()==OPC_INTRPT_STRM && \
						op_intrpt_strm()!=APP_STRM)
#define		SRV		(op_intrpt_type()==OPC_INTRPT_SELF)

#define		MAX_SEQ	255

// routing table entry definition
typedef struct{
	int seq_number;
	int in_strm[4];	//1 means in, 0 means no in
}structseq;

typedef struct{
	int srcaddr;
	structseq seq_num[MAX_SEQ];
	int seq_it;	// iterator
}rttable_entry;
FB:

// Routing table manipulating functions

rttable_entry * rttable_lookup(int src_addr)
	{
	int rt_size, i;
	rttable_entry * rt_entry;
	FIN(rttable_lookup(src_addr));

	rt_size = op_prg_list_size(list_rttable);
	for(i=0; i<rt_size; i++)
		{
		rt_entry = op_prg_list_access(list_rttable, i);
		if(rt_entry->srcaddr == src_addr)
			{
			FRET(rt_entry);
			}
		}
	FRET(OPC_NIL);
	}

void rttable_addEntry(int src_addr, int seq, int instrm)
	{
	rttable_entry * rt_entry;
	int i;
	FIN(rttable_addEntry(src_addr, seq, instrm));
	
	rt_entry = (rttable_entry *)op_prg_mem_alloc(sizeof(rttable_entry));
	rt_entry->srcaddr = src_addr;
	rt_entry->seq_it = 1;
	for(i=0; i<MAX_SEQ; i++)
		{
		rt_entry->seq_num[i].seq_number = 0xFFFF;
		}
	rt_entry->seq_num[0].seq_number = seq;
	rt_entry->seq_num[0].in_strm[instrm] = 1;
	op_prg_list_insert(list_rttable, rt_entry, OPC_LISTPOS_TAIL);
	FOUT;
	}

int rttable_isnewSeq(rttable_entry * rt_entry, int seq)
	{
	int i;
	FIN(rttable_isnewSeq(rt_entry, seq));
	for(i=0; i<MAX_SEQ; i++)
		{
		if(rt_entry->seq_num[i].seq_number == seq)
			FRET(0);
		}
	FRET(1);
	}

void rttable_addSeq(rttable_entry * rt_entry, int seq, int instrm)
	{
	FIN(rttable_addSeq(rt_entry, seq, instrm));
	
	rt_entry->seq_num[rt_entry->seq_it].seq_number = seq;
	rt_entry->seq_num[rt_entry->seq_it].in_strm[instrm] = 1;
	rt_entry->seq_it = (rt_entry->seq_it + 1) % 0xFFFF;
	FOUT;
	}

void rttable_addinstrm(rttable_entry * rt_entry, int seq, int instrm)
	{
	int i;
	FIN(rttable_addinstrm(rt_entry, seq, instrm));
	
	for(i=0; i<MAX_SEQ; i++)
		{
		if(rt_entry->seq_num[i].seq_number == seq)
			rt_entry->seq_num[i].in_strm[instrm] = 1;
		}
	FOUT;
	}

void rttable_getstrm(int src_addr, int seq, int in_strm[])
	{
	int i;
	rttable_entry * rt_entry;
	FIN(rttable_getstrm(src_addr, seq, in_strm));
	rt_entry = rttable_lookup(src_addr);
	for(i=0; i<MAX_SEQ; i++)
		{
		if(rt_entry->seq_num[i].seq_number == seq)
			{
			in_strm[0] = rt_entry->seq_num[i].in_strm[0];
			in_strm[1] = rt_entry->seq_num[i].in_strm[1];
			in_strm[2] = rt_entry->seq_num[i].in_strm[2];
			in_strm[3] = rt_entry->seq_num[i].in_strm[3];
			}			
		}
	FOUT;
	}

init:

// get node id, init the seq
node_id = op_topo_parent(op_id_self()) - 2;
seq_no_self = 0;
list_rttable = op_prg_list_create();
op_intrpt_schedule_self(op_sim_time()+0.5, 0);

Send:

// app gen pkt, set addr and seq
// insert to subq
Packet * pk;

pk = op_pk_get(op_intrpt_strm());
op_pk_nfd_set_int32(pk, "src addr", node_id);
op_pk_nfd_set_int32(pk, "sequence", seq_no_self++);

if(op_subq_pk_insert(0, pk, OPC_QPOS_TAIL) != OPC_QINS_OK)
	{
	op_pk_destroy(pk);
	}

Receive:

// a pkt rcv from other node
// operation refered to the flood example in ns
// get the src addr and seq
// if new src addr, add to route table, insert to subq
// else if old addr, new seq, add seq, insert to subq
// else if old addr, old seq, add strm, destroy

int instrm;
Packet *pk;
int src_addr, seq;
rttable_entry * rt_entry = OPC_NIL;

instrm = op_intrpt_strm();
pk = op_pk_get(instrm);
op_pk_nfd_get_int32(pk, "src addr", &src_addr);
op_pk_nfd_get_int32(pk, "sequence", &seq);

rt_entry = rttable_lookup(src_addr);
if(rt_entry == OPC_NIL)	// new src addr
	{
	rttable_addEntry(src_addr, seq, instrm);
	if(op_subq_pk_insert(0, pk, OPC_QPOS_TAIL) != OPC_QINS_OK)
		{
		op_pk_destroy(pk);
		}
	}
else if(rttable_isnewSeq(rt_entry, seq))	// new sequence
	{
	rttable_addSeq(rt_entry, seq, instrm);
	if(op_subq_pk_insert(0, pk, OPC_QPOS_TAIL) != OPC_QINS_OK)
		{
		op_pk_destroy(pk);
		}
	}
else	// duplicated
	{
	rttable_addinstrm(rt_entry, seq, instrm);
	op_pk_destroy(pk);
	}

Foward_slot

// periodically check subq to implement slotted packet system
// if src addr == self, send to all links
// else send to all other links

Packet * pk, * cpk;
int i;
int src_addr, seq;
int instrm[4];

while(!op_subq_empty(0))
	{
	pk = op_subq_pk_remove(0, OPC_QPOS_HEAD);
	op_pk_nfd_get_int32(pk, "src addr", &src_addr);
	op_pk_nfd_get_int32(pk, "sequence", &seq);
	
	if(src_addr == node_id)
		{
		for(i=0; i<4; i++)
			{
			cpk = op_pk_copy(pk);
			op_pk_send(cpk, i);
			}
		op_pk_destroy(pk);
		}
	else
		{
		rttable_getstrm(src_addr, seq, instrm);
		
		for(i=0; i<4; i++)
			{
			if(instrm[i] != 1)
				{
				cpk = op_pk_copy(pk);
				op_pk_send(cpk, i);
				}
			}
		op_pk_destroy(pk);
		}
	}

op_intrpt_schedule_self(op_sim_time()+0.5, 0);


你可能感兴趣的:(opnet的flood泛洪路由实现)