添加MFlood路由协议的实验
1、协议分析
MFLOOD洪泛协议是一个简单的无线路由协议,其中基本的思想是:节点根据一定的规则转发自己收到的数据包。该协议包括了Mflood.h, Mflood.cc, Mflood-packet.h, Mflood-seqtable.h, Mflood-seqtable.cc五个文件。
(1)Mflood-packet.h定义了mflood的报头格式:
这个新加的报头hdr_mflood通过定义offset_变量,使得能够得到访问。
(2)mflood洪泛协议的实现过程主要在Mf
lood.cc中体现。在Mflood.cc中有三个主要的函数,rt_resolve用于建立新的路由,recv用于接收数据包,forward用于转发数据包。具体流程如下:
首先进行初始化,如果自己是发送端,那么给这个包加上IP头(长度为20)。设置ttl并且将mflood报头seq栏位中的序号加1。进行转发。
如果IP报头中的源节点地址指向了自己,说明该节点收到了自己发送的包,显然需要丢弃该包。
如果节点本身不是数据发送的发起者,收到的也不是自己作为数据发起着发送的数据包,那么节点对ttl进行判断,如果ttl为零,同样丢弃这个数据包。
如果上述情况都不是,说明该节点需要转发这个与自己无关的包,在转发之前,需要对这个包进行判断,看它符不符合转发的规则。因此,调用了rt_resolve(p)函数。
(3)rt_resolve(p)函数
节点转发数据包之前,必须对这个数据包进行判断,首先查看节点本身的路由中查看数据包的源节点地址,如果不存在,则更新RTEntry,创建路由表,转发该数据包。如果数据包携带的源地址存在,则判断该数据包的seq是否是一个新的seq。
判断的方法就是采用一个大小为REM_SEQ_COUNT的seqnos[]数组存放收到的数据包的seq。由于seq越大,数据包越新,所以如果新收到的数据包的seq大于以保存的max_seq,说明这是一个新的数据包,返回true,如果新收到的包的seq小于min_seq,说明这是很久以前的包了,返回false,同样的,遍历rt_seqnos[]数组,如果已存在相同的seq,说明曾经转发过这个数据包,也返回false。判断完毕后,修改seqno相关信息,并根据判断结果转发这个数据包。修改seqno方法如下:
加入刚刚进行判断的数据包的seq小于min_seqno,直接返回,如果大于max_seqno,更新最大的序号,把这个seq存放到rt_seqnos[]数组中。最后遍历整个数组,找出min_seqno。这里对seq_it取余的操作目的在于如果存放的seq多余REM_SEQ_COUNT,那么就重新开始保存。
(4)对数据包的转发:
转发的时候,首先考虑转发的是否为广播包,如果是广播包需要考虑时延,如果不是广播包,则无需时延直接发送。值得注意的是,转发的时候,必须将公共报头中的方向栏位赋值向下,以改变包的传播方向,使之向下传递。
整个发包的过程基本完成。
2、协议添加
(1)将Mflood.h, Mflood.cc, Mflood-packet.h, Mflood-seqtable.h, Mflood-seqtable.cc五个文件添加至~/ns2.29/mflood文件夹中。
(2)由于添加了新的报头hdr_mflood,因此需要修改packet.h文件。
(3)MFlood是一个新的无线网络路由协议,因此需要修改ns-lib.tcl文件
(4)在makefile.in中添加mflood/mflood.o mflood/mflood-seqtable.o \
(5)./configure make clean make depend make
3、调试
添加一个新的路由协议难免会出现错误,不过我很幸运,基本都是语法错误,按照make error提示的错误挨个检查,每次修改之后make一遍,知道最后make成功。
4、测试脚本
测试了三个无线节点,tcl简单,节点0发送,节点2接收,下面是得到的trace文件。
s 10.000000000 _0_ AGT --- 0 cbr 512 [0 0 0 0] ------- [0:0 2:0 32 0] [0] 0 0
r 10.000000000 _0_ RTR --- 0 cbr 512 [0 0 0 0] ------- [0:0 2:0 32 0] [0] 0 0
s 10.000000000 _0_ RTR --- 0 cbr 532 [0 0 0 0] ------- [0:0 2:0 30 0] [0] 0 0
r 10.004812500 _1_ RTR --- 0 cbr 532 [0 ffffffff 0 800] ------- [0:0 2:0 30 0] [0] 1 0
f 10.006574953 _1_ RTR --- 0 cbr 532 [0 ffffffff 0 800] ------- [0:0 2:0 29 0] [0] 1 0
r 10.011667453 _0_ RTR --- 0 cbr 532 [0 ffffffff 1 800] ------- [0:0 2:0 29 0] [0] 2 0
D 10.011667453 _0_ RTR DROP_ROUTE_LOOP 0 cbr 532 [0 ffffffff 1 800] ------- [0:0 2:0 29 0] [0] 2 0
r 10.011667453 _2_ AGT --- 0 cbr 532 [0 ffffffff 1 800] ------- [0:0 2:0 29 0] [0] 2 0
在10.0s时应用层CBR发生器从节点0往节点2发送大小为512字节的UID为0数据包,
2 几乎不需要时间该数据包就到达发送节点(节点0)的路由层(即网络层)
3 节点0在路由层发送广播分组加上Common,IP首部20字节给节点2(UDP分组头部NS不计算在内)
4 节点1的路由层收到0节点广播过来的UID为0数据包538字节
5 节点1转发刚广播过来的UID为0数据包
6 节点0在网络层又收到1转发过来(本是自己发送出去的UID为0的数据包)
7 节点0知道了这个包是自己发出去的,所以drop掉
8 节点2收到节点0广播的并由节点1转发的UID为0的数据包。。。。
问题1 mflood报头中的dst_group未用
问题2 initialized()函数返回中的target_是什么?
问题3 command函数的作用?
问题4 关于RTEntry类和MFlood类的关系怎样去理解?