AODV协议
1、概述
本文只是大致介绍AODV协议流程,重点介绍思想以及收发消息,并不严谨,详细见RFC3561。
AODV的一个显著特点是它在每个路由表项上使用了目的序列号。目的序列号由目的节点创建,并且被包含在路由信息中,然后这些路由信息将被回发到所有向它发起请求的节点。目的序列号的使用确保了无回环,并且易于编程,因此,路由回路以及无穷计数问题得以解决。如果到一个目的有两条路由可供选择,那么收到请求的节点将会选择序列号最大的那一条(由于目的节点每次收到新的请求都会将目的序列号加一,所以序列号最大表明该路由最新)。
AODV使得移动节点能快速获得通向新的目的节点的路由,并且节点仅需要维护通向它信号所及范围内的节点的路由,更远的节点的路由信息则不需要维护,也就是说,通常AODV仅仅记住下一跳的节点。
1.1、基本流程
路由请求(RREQ),路由回复(RREP)和路由错误(RERR)是AODV定义的三种消息种类。这些消息通过UDP和通常的IP协议来接收。
只要一条通道连接的两个端点都有通向对方的正确路由,AODV是不工作的。当某节点需要连接到一个新的目的节点时,它将广播一个RREQ(路由请求消息)来尝试找到一条到目的节点的路由。如果RREQ消息到达目的节点,这条路由将被找到。另外一种情况下,路由也可以找到,就是RREQ到达了一个中间节点,该中间节点拥有到目的节点的“足够新鲜”的路由。“足够新鲜”的路由首先要是一条到目的地的正确路由,该路由还需要拥有一个足够大的序列号,该序列号不得小于RREQ中的序列号(原文为:A ‘fresh enough’ route is a valid route entry for the destination whose associated sequence number is at least as great as that contained in the RREQ.)。当中间节点朝发起RREQ的节点单播一个RREP后,这条路由就建立了。所有接到请求的节点都会缓存一条回到发起节点的路由,所以RREP就可以通过单播从目的节点返回到发起节点,或者从一个能够找到目的节点的中间节点返回到发起节点。
为了实现以上过程,每个节点都要维护自己的序列号,并且将网络中其他节点的序列号储存起来。
节点将相邻节点(next hops)的连接状态保存在活动路由表里(active routes)。当活动路由表里有一条连接断开时,一条RERR消息(路由错误消息)将被用来通知其他节点发生了连接断裂。RERR消息指出了不再能到达的目的节点(甚至是目的子网)。为了实现这种报告机制,每个节点还要维护一个“先驱表”(precursor list),表中包含了一些邻居的IP,这些邻居可能会将它用作达到目的地的下一跳节点。先驱表里的信息可以很轻易的从回传RREP的过程中获得。
1.2、路由表
AODV的每个路由表项将会包含下列的域:
- 目的节点IP地址
- 目的节点序列号
- 目的节点序列号是否正确的标志
- 其他状态和路由标志(比如,有效,无效,可修复,正在修复)
- 网络接口
- 跳数(到达目的节点需要的跳数)
- 下一跳
- 先驱表
- TTL(路由过期或应当删除的时间)
1.3、一些比较难以理解的术语
- Active route(活跃路由)
路由表项里标为“有效”(valid)的通向目的节点的路由。只有活跃路由能用来转发数据包。 - Reverse route (返回路由)
用于转发回复包的路由,这个回复包就是从目的节点或能达到目的节点的中间节点返回到发起节点的RREP包。 - Sequence number (序列号)
一个单调递增的数字,由每个发起节点管理。在AODV路由协议的消息里,这个序列号被其他节点用于检测发起节点发出的信息的新旧程度。
2、序列号处理
每一个节点的每一个路由表项必须包含关于目的节点(路由表就是为此而维护的)IP地址的序列号的最新可用信息。这个序列号叫做“目的序列号”。如果在任何时候一个节点接收到了新的(即未失效的)信息,而这个信息是跟RREQ,RREP,或者RERR消息中的序列号有关的话,目的序列号就会更新。
AODV要求在网络中的每一个节点都要拥有并维护其目的序列号,以避免无穷计数问题。在两种情况下,目的节点会增加它自己的序列号:
- 在一个节点发起一个路径发现的请求之前,他必须增加它自己的序列号。这样,对于已经建立好了的朝向RREQ消息发起者的反向路由来说,可以防止本次请求与其相冲突(防止无穷计数)。
- 在目的节点生成RREP消息以响应RREQ消息之前,它必须更新它自己的序列号,新的值是它目前的序列号和RREQ消息包中目的序列号的较大者。
当目的节点要增加它的序列号时,它必须以无符号数的形式来处理序列号。
为了确定目的节点的信息是否是新的,当前节点会拿自己目前的序列号数跟接收到的AODV信息中的序列号数相比较。如果从接收到的序列号数减去当前序列号的结果小于0的话,那么这个接收到的有关目的节点的AODV信息就必须被丢弃,因为跟节点当前所保存的信息相比,接收到的信息更加陈旧。
另外,节点为了修复路由路径中丢失了的或者过期了的下一跳时,可能会改变其路由表项中的目的序列号,这也是除了以上情况以外唯一要改变目的序列号的情况。节点通过查询其路由表来查询都有哪些目的节点使用了这个不可使用的下一跳节点。在这种情况下,对于每一个使用这个节点的目的节点,当前节点都会增加其序列号并把此路径标记为不可用。
一旦节点接收到了一个足够新的(也就是包含大于等于本节点所记录的序号),并且是来自于已经标记相应路由表项为不可用的节点的路由信息时,当前节点应该以新的信息来更新其路由表信息。
3、路由表以及先驱表
当一个节点从它的邻居接收到一条AODV控制包时,以及为某个特定的目的节点或目的子网创建或更新它的路由表的时候,它就会去检查它的路由表里是否有一个表项对应到那个目的。当没有相关的表项时,新的表项就会被创建。序列号要么就是从AODV控制消息里提取的,要么就干脆在路由表项里“序列号有效”这个位置标明“无效”。仅在新的序列号满足下列三种条件时路由会更新:
- 新序列号要比路由表里原来的原目的序列号大。
- 序列号相等,但是新信息里包含的跳数加一还要比原来的跳数小。
- 新序列号是未知的。
对每个放在路由表项里的有效路由,节点还会维护一张先驱表。路由表项里的先驱列表包含的是都是本节点的相邻节点,路由回复信息将会被发送到这些节点。
4、生成路由请求
当一个节点无法找到一个可用的到某个节点的路由时,它就会广播一条RREQ消息。出现这种情况可能是由于这个节点以前并不知道有这么一个目的节点,也可能是由于以前到该目的节点的有效路由过期了,或是被标记为无效。
RREQ消息的“Destination Sequence Number”这个域应当填最近一次获得的该节点的目的节点序列号。如果尚未获得任何目的节点序列号,则“序列号未知”标志必须被置位。
RREQ里的“Originator Sequence Number”就是发起节点自己的序列号,在把它放入RREQ消息里时,它得先自增1。
消息里“RREQ ID”则是将当前节点以前用过的RREQ ID加一。每个节点只维护一个RREQ ID。“Hop Count”填0。
在发送出去以后,发送节点会缓存一段时间的RREQ ID和Originator IP address(就是它自己的IP地址),如果收到与以上两个条目相同的RREQ则会丢弃。
一个发送节点可以尝试多次发送,每次发送增加TTL,从而扩大传输范围,同时使用指数退避原则避免网络拥塞。
一个发起节点总是想和目的节点建立双向的通信,即,仅仅是发起节点有到目的节点的路由还不够,目的节点还必须拥有回到发起节点的路由。为了尽力有效的实现这个特性,每个中间节点在生成RREP回发给发起节点的同时,还必须执行某种操作,用于告知目的节点一条返回发起节点的路由。当发起节点需要让中间节点作出上述操作的时候,它需要将RREQ的“G”标志位置位(Gratuitous RREP flag 免费路由回复标志)。
5、传播时间间隔的计算
为了防止RREQ消息在整个网络内散布得到处都是,发起节点应当逐次的扩大搜索范围。在范围逐次扩大的搜索中,发起节点最初会设置RREQ包的IP头内的TTL值为TTL_START,设置等待RREP的超时时间为RING_TRAVERSAL_TIME毫秒。用于计算RING_TRAVERSAL_TIME的TTL_VALUE的值被设置成等于IP头中的TTL值。如果发出RREQ后等待RREP超时,发起节点将再次广播RREQ,而这次的TTL值将被加上TTL_INCREMENT。这样一直持续到RREQ包内的TTL达到阈值TTL_THRESHOLD。在达到阈值后,每次使用的TTL都将被设置为NET_DIAMETER。每次等待RREP的超时时间都是RING_TRAVERSAL_TIME。如果需要每次路由寻找都在整个Ad Hoc网络范围内进行,可以将TTL_START和TTL_INCREMENT都设置为等于NET_DIAMETER来达到目的。
6、转发路由请求
当一个节点收到一条RREQ消息时,它首先创建一个到前一跳节点的路由,或者更新原来已有的,但序列号不对的到上一跳的路由(“上一跳”是为了以后的反向路由)。然后检查它在PATH_DISCOVERY_TIME时间内是否受到过具有相同Originator IP Address和RREQ ID的RREQ消息。如果已经接收过了,那么这个节点就会丢弃这个RREQ,不作任何操作。否则:
首先,该节点会将RREQ消息内的跳数加一,表明该RREQ又跳过了一个中间节点。然后该节点会搜索到发起节点IP地址的反向路由。如果有必要,这条路由会被创建。当该节点接收到一条RREP需要回传到发起节点时,这条路由就会被用到(RREP消息送达的目的如果和RREQ消息内的Originator IP Address一样,则说明这条RREP消息是对该RREQ的回复,于是在接收RREQ时创建的反向路由就可以被用到了)。当反向路由被创建或更新时,将对它执行以下操作。
- RREQ消息内的Originator Sequence Number(发起节点序列号)会被用来和反向路由里对应的目的节点序列号比较,如果比已经在路由表里的那个大,那么就会被复制到路由表里面。
- 路由表项里“序列号有效”一栏会被设置为“有效”
- 反向路由表项里的“下一跳”将被设置为传递RREQ给本节点的那个相邻节点。
- 反向路由表项里“跳数”直接从RREQ消息内的“跳数”复制而来。
- 如果本节点不是目的节点,即不生成RREP信息,那么本节点将进行广播。如果本节点就是目的节点,那么本节点生成RREP信息,丢掉RREQ信息。
7、“G”
如果中间节点对送往特定目的节点的RREQ的每一次传递都作出回复的话,可能会导致目的节点收不到任何路由发现信息(有可能其他节点收到了RREQ,而它知道一条到目的节点的路由,于是它就会发回一个RREP,同时丢弃掉RREQ,这样,目的节点就会这次路由发现过程毫不知情)。在这种情况下,目的节点不会从RREQ消息上获得通往发起节点的路由。而这可能会导致目的节点发起一个到发起节点的路由发现过程(例如,如果发起节点试图和目的节点建立一个TCP连接的情况)。为了使目的节点也能得到返回发起节点的路由,不管是出于什么原因,只要觉得目的节点需要一条返回路由,发起节点就应当将RREQ消息内的“Gratuitous RREP”标志位(G)置位。如果一个中间节点为响应一条带“G”标志的RREQ而向发起节点回复了一个RREP,那么它也必须免费向目的节点送出一条RREP消息。
8、路由回复
一个节点在下面两种情况下会生成一条路由回复消息:
- 它自己就是目标节点。
- 它到目的节点有一条有效路由,且路由表项内的目的节点序列号有效并且不小于RREQ消息内的目的节点序列号(以32位有符号数的格式进行比较),且RREQ内的“仅目的节点回复”标志位(D)未被置位。
9、接收路由回复
更新跳数等信息,然后建立(更新)路由
如果一个节点通过以上链接转发一个可能出错或是单向的RREP,这个节点应该将“A”标志位置位以指示此RREP包的接受者送回以个RREP-ACK包确认已接受到该包。
10、单向链怎么办?
当一个节点检测到它传送的RREP失败,它将把失效RREP的下一跳记入“黑名单”设置。这些失败可以不通过链路层或者网络层的承认(如,RREP-ACK)。如果本节点发现从黑名单中收到了一个RREQ,则忽略。**任何节点只对第一个带有相同RREQ ID的 RREQ包起作用并忽略其它随后的RREQ包。**ACK的作用是用于防止“第一个RREQ沿着一条有一个或多个单向链接的路径到达;一个随后的RREQ可能通过一个双向路径(假设存在这样的路径)到达,但它会被忽略“这样的问题
11、HELLO信息
即TTL = 1的RREP信息。一个节点可以通过广播本地Hello消息提供连接信息。当一个节点在一段时间之后都没有收到来自邻居节点的HELLO消息,则应该认为二者之间链路中断。每当一个节点从临近节点收到一个Hello消息,该节点应该确保它与此临近节点有一条活动的路由,如果有必要则创建一条。
13、与DSR的区别
12、参考文献
C. Perkins, E. Belding-Royer and S. Das. Ad hoc On-Demand Distance Vector (AODV) Routing., RFC 3561, July 2003