• AODV路由协议的路由缓存队列详解


    AODV路由协议的使用往往在一些复杂的程序当中。那么我们如何理解这些协议的使用和一些代码函数的含义呢?下面我们就来阐述一下这方面的问题。首先了解一下在NS2.27中,AODV路由协议主要包括以下几个组件:

    1、协议实体

    2、路由表

    3、定时器

    (1)广播定时器

    (2)周期Hello报文广播定时器

    (3)用于邻居管理的定时器

    (4)用于路由缓存的定时器

    (5)用于本地修复的定时器

    (6)缓存广播ID的定时器

    4、日志记录器

    5、路由缓存队列

    首先来看AODV路由协议从接收到一个分组开始的基本流程。

    当协议接收到一个分组,即recv(Packet*, Handler*)函数被调用,函数根据分组类型调用不同的处理函数进行处理。

    1、如果是协议分组,则将分组的ttl值减1,并调用recvAODV(Packet*)函数进行处理。recvAODV函数再根据分组的不同类型来调用不同的函数进行处理。

    (1)如果接收到的是路由请求分组,则调用recvRequest(Packet*)函数进行处理。

    如果该分组由节点自身产生或已经接收过的,会被节点丢弃,并结束处理。

    否则,节点将缓存该分组的序列号,并将该分组发送来的路径添加到反向路由中,转发相应分组。然后,节点根据该分组的目的地址进行判断并调用不同函数进行处理。

    如果节点自身即为目的节点,则调用sendReply(nsaddr_t, u_int32_t, nsaddr_t, u_int32_t, u_int32_t, double)函数进行响应。如果节点不是目的节点,但知道通往目的节点的路由,则调用sendReply函数进行响应,并在源和目的前驱列表中分别插入到源和目的的下一跳节点。否则,不能直接响应该请求,将跳数加1,并调用forward(AODV_rt_entry*, Packet*, double)函数转发该分组。

    在sendReply函数中,节点首先查找到达目的节点(即发送路由请求分组的节点)的路由,创建并填充分组,然后调用Scheduler::instance().schedule()函数来发送该分组。

    (2)如果接收到的是路由响应分组,则调用recvReply(Packet*)函数进行处理。

    节点首先查询前往分组目的节点的路由,如果不存在则新增一条路由项。然后,节点更新到该目的节点的路由项,并发送所有相关分组。

    如果节点为目的节点则更新路由发现延迟并发送所有相关的分组。如果节点不是目的节点,但知道通往目的节点的路由,则将跳数加1,调用forward函数转发该分组,并修改响应的前驱列表。如果节点不是目的节点,也不知道通往目的节点的路由,则丢弃该分组。

    (3)如果接收到的是路由错误分组,AODV路由协议则调用recvError(Packet*)函数进行处理。

    节点首先清除所有受到影响的路由项,丢弃所有受影响的分组。然后,如果前驱节点中存在会受该路由错误影响的分组,则调用sendError(Packet*, bool)函数转发该分组。

    sendError函数创建并填充分组,然后调用Scheduler::instance().schedule()函数来发送该分组。

    (4)如果接收到的是Hello消息分组,则调用recvHello(Packet*)函数进行处理。

    节点会将该邻居的信息添加到邻居列表中(或更新该邻居的信息)。

    2、如果是数据分组,则节点丢弃已经发送过或者ttl为0的分组,并结束处理。如果分组是由上层协议产生的,则节点添加IP报头。随后,节点根据目的路由进行不同处理。

    (1)如果目的节点路由未知,则调用rt_resolve(Packet*)函数进行路由解析和转发。

    如果目的节点路由在路由表中存在,则直接调用forward函数进行转发。如果分组是由节点自身产生的,则将分组保存到缓冲队列中,并调用 sendRequest(nsaddr_t)函数查询目的路由。如果目的路由已知,但正在进行本地修复,则将分组保存到缓冲队列中。否则,丢弃该分组,并调用sendError函数报错。

    (2)如果目的节点路由已知,则调用forward进行转发。

    节点丢弃ttl为0的分组,并根据分组类型决定下一步操作。

    如果接收到的是数据分组,且自身为目的节点,则通过调用PortClassifier对象的recv(Packet*, Handle*)函数将分组交递给高层协议,并结束处理。否则,节点设置分组属性,并调用Scheduler::instance().schedule (Handler*, Event*, double)函数来发送分组。其中,Handler为基类中的属性target_(会根据脚本中的设置指向相应的协议实体),Event为要发送的分组即可。

    以上就是AODV路由协议在节点收到分组后的一个处理过程。接下来看看各个定时器所做的工作。

    1、广播定时器BroadcastTimer在到时后调用id_purge()函数删除广播项中已超时的项目,并通过调用Scheduler:: instance().schedule()函数来设置下次被调用的时间(Handler为this指针,Event为类属性intr)。

    2、周期Hello报文广播定时器HelloTimer在到时后调用sendHello()函数向邻居创建并发送Hello消息,并调用schedule()函数来设置下次被调用的时间。

    3、邻居管理定时器NeighborTimer在到时后调用nb_purge()函数来清除邻居列表中已超时的邻居项,并调用schedule()来设置下次被调用的时间。nb_purge会调用nt_delete(nsaddr_t)函数来清除超时的邻居项,其又会调用 handle_link_failure(nsaddr_t)函数来处理由于邻居节点被删除而引起的路由变化。

    4、路由缓存定时器RouteCacheTimer在到时后调用rt_purge()函数来清除路由表中已超时的路由项,并丢弃相关的分组,再调用schedule()来设置下次被调用的时间。

    5、本地修复定时器LocalRepairTimer在调用后根据传递的分组的目的地址关闭相应的路由项。

    6、缓存广播ID定时器BroadcastID用来保存广播分组的ID。

    此外,AODV路由协议的路由表、日志记录和队列三个类就相对比较简单了,都只实现了一些非常基本的功能,在此就不做介绍了

  • 相关阅读:
    react 全局监听报错,监听白屏
    【Python】(八)Python中的set集合(每个人都是唯一的个体)
    【Python】(六)Python数据类型-列表和元组,九浅一深,用得到
    mybatis-spring多数据源配置
    自己动手实现springboot运行时新增/更新外部接口
    自己动手实现springboot运行时执行java源码(运行时编译、加载、注册bean、调用)
    自己动手实现java断点/单步调试(一)
    自己动手实现java断点/单步调试(二)
    Swift 模式下面LLDB 输出对象
    Understanding Swift’s value type thread safety
  • 原文地址:https://www.cnblogs.com/zhangleiccst/p/2210791.html
Copyright © 2020-2023  润新知