NS3中路由协议分析【AODV代码分析】

详尽分析aodv-routing-protocol.cc代码

  • 预处理命令
    包括宏定义#define 和 引入头文件#include
#define NS_LOG_APPEND_CONTEXT                                   \
  if (m_ipv4) {
    std::clog << "[node " << m_ipv4->GetObject<Node> ()->GetId () << "] "; }

#include "aodv-routing-protocol.h"
#include "ns3/log.h"
#include "ns3/boolean.h"
#include "ns3/random-variable-stream.h"
#include "ns3/inet-socket-address.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/packet.h" // trace
#include "ns3/udp-socket-factory.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/udp-header.h"
#include "ns3/wifi-net-device.h"
#include "ns3/adhoc-wifi-mac.h"
#include "ns3/string.h"
#include "ns3/pointer.h"
#include <algorithm>
#include <limits>
  • 进入ns3命名空间后为日志组建命名
namespace ns3
NS_LOG_COMPONENT_DEFINE ("AodvRoutingProtocol");
  • 进入aodv命名空间
    注册一个新的RoutingProtocol类
    设置AODV控制流使用的UDP端口号为654
namespace aodv
NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
const uint32_t RoutingProtocol::AODV_PORT = 654; 

-设置AODV实现使用的标记
标记数据包中的一组字节。可以通过这个抽象基类的子类创建新类型的标记

class DeferredRouteOutputTag : public Tag
{
   

public:
  DeferredRouteOutputTag (int32_t o = -1) : Tag (), m_oif (o) {
   }

  static TypeId GetTypeId ()
  {
   
    //class ns3::TypeId 接口的唯一标识符。这个类记录了关于Object基类的一个子类的大量元信息,包括子类的基类,子类中可访问的构造函数集,子类内可访问的“属性”集
    static TypeId tid = TypeId ("ns3::aodv::DeferredRouteOutputTag") //括号内为:要构造的接口的名称
      .SetParent<Tag> ()
      .SetGroupName("Aodv")
      .AddConstructor<DeferredRouteOutputTag> ()
    ;
    return tid;
  }

  TypeId  GetInstanceTypeId () const
  {
   
    return GetTypeId ();
  }

  int32_t GetInterface() const
  {
   
    return m_oif;
  }

  void SetInterface(int32_t oif)
  {
   
    m_oif = oif;
  }

  uint32_t GetSerializedSize () const
  {
   
    return sizeof(int32_t);
  }

  void  Serialize (TagBuffer i) const
  {
   
    i.WriteU32 (m_oif);
  }

  void  Deserialize (TagBuffer i)
  {
   
    m_oif = i.ReadU32 ();
  }

  void  Print (std::ostream &os) const
  {
   
    os << "DeferredRouteOutputTag: output interface = " << m_oif;
  }

private:
  /// Positive if output device is fixed in RouteOutput 如果输出设备在RouteOutput固定,则为正
  int32_t m_oif;
};
  • 注册一个新的DeferredRouteOutputTag类
NS_OBJECT_ENSURE_REGISTERED (DeferredRouteOutputTag);
  • 设置RoutingProtocol的属性
RoutingProtocol::RoutingProtocol () :
  m_rreqRetries (2), //重传RREQ的最大数目
  m_ttlStart (1), //RREQ的TTL初始值
  m_ttlIncrement (2), //在RREQ传播中每次尝试使用扩展环搜索的TTL增加值
  m_ttlThreshold (7), //扩展环搜索中最大的TTL值
  m_timeoutBuffer (2), //为超时提供缓冲区
  m_rreqRateLimit (10), //每秒RREQ的最大数目
  m_rerrRateLimit (10), //每秒RERR的最大数目
  m_activeRouteTimeout (Seconds (3)), //路由有效的时间长度
  m_netDiameter (35), //测量网络中两节点最大可能的跳数
  m_nodeTraversalTime (MilliSeconds (40)), //保守估计数据包的每一跳传输时间,包括队列等待时间、中断处理时间、传输时间
  m_netTraversalTime (Time ((2 * m_netDiameter) * m_nodeTraversalTime)), //估计网络传播平均时间
  m_pathDiscoveryTime ( Time (2 * m_netTraversalTime)), //估计网络中发现路由所需的的最大时间
  m_myRouteTimeout (Time (2 * std::max (m_pathDiscoveryTime, m_activeRouteTimeout))), //该节点产生的RREP中生存时间域的值
  m_helloInterval (Seconds (1)), //每个hello消息间隔,节点检查自己是否在上一个hello间隔中发送了一个广播消息。若无,该节点可能发送一个hello消息
  m_allowedHelloLoss (2), //有效链接可能丢失的hello消息数
  m_deletePeriod (Time (5 * std::max (m_activeRouteTimeout, m_helloInterval))), //提供节点A能将邻居节点B作为下一跳节点的(目的地为D)的时间上限,此时节点B到节点D的路由无效
  m_nextHopWait (m_nodeTraversalTime + MilliSeconds (10)), //等待邻居节点回复RREP_ACK的时间
  m_blackListTimeout (Time (m_rreqRetries * m_netTraversalTime)), //将那个节点加入黑名单的时间
  m_maxQueueLen (64), //路由协议允许缓冲的最大数据包数目
  m_maxQueueTime (Seconds (30)), //路由协议允许的缓冲一个数据包的最大时间
  m_destinationOnly (true), //指示只有目的节点才能回复RREQ
  m_gratuitousReply (true), //指示一个RREP是否应该单播到发起路由发现的节点
  m_enableHello (false), //指示一个hello消息是否可行
  m_routingTable (m_deletePeriod), //路由表
  m_queue (m_maxQueueLen, m_maxQueueTime), //路由层缓存未找到路由的数据包时,采用drop-front队列
  m_requestId (0), //广播ID
  m_seqNo (0), //request序列号
  m_rreqIdCache (m_pathDiscoveryTime), //处理重复的RREQ
  m_dpd (m_pathDiscoveryTime), //处理广播/多播的数据包
  m_nb (m_helloInterval), //处理邻居
  m_rreqCount (0), //RREQ速率控制使用的RREQ数量
  m_rerrCount (0), //RERR速率控制使用的RERR数量
  m_enableEtx (true), //启用ETX度量的链路探测数据包
  m_lppInterval (Seconds (1)), //LPP间隔
  m_lppTimer (Timer::CANCEL_ON_DESTROY), //链路探测包计时器
  m_htimer (Timer::CANCEL_ON_DESTROY), //hello计时器
  m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY), //RREQ速率限制计时器
  m_rerrRateLimitTimer (Timer::CANCEL_ON_DESTROY), //RERR速率限制计时器
  m_lastBcastTime (Seconds (0)) //跟踪上次广播时间
  • 设置链路失败回调
m_nb.SetCallback (MakeCallback (&RoutingProtocol::SendRerrWhenBreaksLinkToNextHop, this));
  • 声明TypeID中新的属性
TypeId
RoutingProtocol::GetTypeId (void)
{
   
  static TypeId tid = TypeId ("ns3::aodv::RoutingProtocol")
    .SetParent<Ipv4RoutingProtocol> ()
    .SetGroupName("Aodv")
    .AddConstructor<RoutingProtocol> ()
    .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
                   TimeValue (Seconds (1)),
                   MakeTimeAccessor (&RoutingProtocol::m_helloInterval),
                   MakeTimeChecker ())
    .AddAttribute ("TtlStart", "Initial TTL value for RREQ.",
                   UintegerValue (1),
                   MakeUintegerAccessor (&RoutingProtocol::m_ttlStart),
                   MakeUintegerChecker<uint16_t> ())
    .AddAttribute ("TtlIncrement", "TTL increment for each attempt using the expanding ring search for RREQ dissemination.",
                   UintegerValue (2),
                   MakeUintegerAccessor (&RoutingProtocol::m_ttlIncrement),
                   MakeUintegerChecker<uint16_t> ())
    .AddAttribute ("TtlThreshold", "Maximum TTL value for expanding ring search, TTL = NetDiameter is used beyond this value.",
                   UintegerValue (7),
                   MakeUintegerAccessor (&RoutingProtocol::m_ttlThreshold),
                   MakeUintegerChecker<uint16_t> ())
    .AddAttribute ("TimeoutBuffer", "Provide a buffer for the timeout.",
                   UintegerValue (2),
                   MakeUintegerAccessor (&RoutingProtocol::m_timeoutBuffer),
                   MakeUintegerChecker<uint16_t> ())
    .AddAttribute ("RreqRetries", "Maximum number of retransmissions of RREQ to discover a route",
                   UintegerValue (2),
                   MakeUintegerAccessor (&RoutingProtocol::m_rreqRetries),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("RreqRateLimit", "Maximum number of RREQ per second.",
                   UintegerValue (10),
                   MakeUintegerAccessor (&RoutingProtocol::m_rreqRateLimit),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("RerrRateLimit", "Maximum number of RERR per second.",
                   UintegerValue (10),
                   MakeUintegerAccessor (&RoutingProtocol::m_rerrRateLimit),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("NodeTraversalTime", "Conservative estimate of the average one hop traversal time for packets and should include "
                   "queuing delays, interrupt processing times and transfer times.",
                   TimeValue (MilliSeconds (40)),
                   MakeTimeAccessor (&RoutingProtocol::m_nodeTraversalTime),
                   MakeTimeChecker ())
    .AddAttribute ("NextHopWait", "Period of our waiting for the neighbour's RREP_ACK = 10 ms + NodeTraversalTime",
                   TimeValue (MilliSeconds (50)),
                   MakeTimeAccessor (&RoutingProtocol::m_nextHopWait),
                   MakeTimeChecker ())
    .AddAttribute ("ActiveRouteTimeout", "Period of time during which the route is considered to be valid",
                   TimeValue (Seconds (3)),
                   MakeTimeAccessor (&RoutingProtocol::m_activeRouteTimeout),
                   MakeTimeChecker ())
    .AddAttribute ("MyRouteTimeout", "Value of lifetime field in RREP generating by this node = 2 * max(ActiveRouteTimeout, PathDiscoveryTime)",
                   TimeValue (Seconds (11.2)),
                   MakeTimeAccessor (&RoutingProtocol::m_myRouteTimeout),
                   MakeTimeChecker ())
    .AddAttribute ("BlackListTimeout", "Time for which the node is put into the blacklist = RreqRetries * NetTraversalTime",
                   TimeValue (Seconds (5.6)),
                   MakeTimeAccessor (&RoutingProtocol::m_blackListTimeout),
                   MakeTimeChecker ())
    .AddAttribute ("DeletePeriod", "DeletePeriod is intended to provide an upper bound on the time for which an upstream node A "
                   "can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D."
                   " = 5 * max (HelloInterval, ActiveRouteTimeout)",
                   TimeValue (Seconds (15)),
                   MakeTimeAccessor (&RoutingProtocol::m_deletePeriod),
                   MakeTimeChecker ())
    .AddAttribute ("NetDiameter", "Net diameter measures the maximum possible number of hops between two nodes in the network",
                   UintegerValue (35),
                   MakeUintegerAccessor (&RoutingProtocol::m_netDiameter),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("NetTraversalTime", "Estimate of the average net traversal time = 2 * NodeTraversalTime * NetDiameter",
                   TimeValue (Seconds (2.8)),
                   MakeTimeAccessor (&RoutingProtocol::m_netTraversalTime),
                   MakeTimeChecker ())
    .AddAttribute ("PathDiscoveryTime", "Estimate of maximum time needed to find route in network = 2 * NetTraversalTime",
                   TimeValue (Seconds (5.6)),
                   MakeTimeAccessor (&RoutingProtocol::m_pathDiscoveryTime),
                   MakeTimeChecker ())
    .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a routing protocol to buffer.",
                   UintegerValue (1024), //originaly it was 64
                   MakeUintegerAccessor (&RoutingProtocol::SetMaxQueueLen,
                                         &RoutingProtocol::GetMaxQueueLen),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("MaxQueueTime", "Maximum time packets can be queued (in seconds)",
                   TimeValue (Seconds (30)),
                   MakeTimeAccessor (&RoutingProtocol::SetMaxQueueTime,
                                     &RoutingProtocol::GetMaxQueueTime),
                   MakeTimeChecker ())
    .AddAttribute ("AllowedHelloLoss", "Number of hello messages which may be loss for valid link.",
                   UintegerValue (2),
                   MakeUintegerAccessor (&RoutingProtocol::m_allowedHelloLoss),
                   MakeUintegerChecker<uint16_t> ())
    .AddAttribute ("GratuitousReply", "Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.",
                   BooleanValue (true),
                   MakeBooleanAccessor (&RoutingProtocol::SetGratuitousReplyFlag,
                                        &RoutingProtocol::GetGratuitousReplyFlag),
                   MakeBooleanChecker ())
    .AddAttribute ("DestinationOnly", "Indicates only the destination may respond to this RREQ.",
                   BooleanValue (true),
                   MakeBooleanAccessor (&RoutingProtocol::SetDestinationOnlyFlag,
                                        &RoutingProtocol::GetDestinationOnlyFlag),
                   MakeBooleanChecker ())
    .AddAttribute ("EnableHello", "Indicates whether a hello messages enable.",
                   BooleanValue (false),
                   MakeBooleanAccessor (&RoutingProtocol::SetHelloEnable,
                                        &RoutingProtocol::GetHelloEnable),
                   MakeBooleanChecker ())
    .AddAttribute ("EnableBroadcast", "Indicates whether a broadcast data packets forwarding enable.",
                   BooleanValue (true),
                   MakeBooleanAccessor (&RoutingProtocol::SetBroadcastEnable,
                                        &RoutingProtocol::GetBroadcastEnable),
                   MakeBooleanChecker ())
    .AddAttribute ("UniformRv",
                   "Access to the underlying UniformRandomVariable",
                   StringValue ("ns3::UniformRandomVariable"),
                   MakePointerAccessor (&RoutingProtocol::m_uniformRandomVariable),
                   MakePointerChecker<UniformRandomVariable> ())
    .AddAttribute ("EnableEtx", "Enable ETX metrix.",
                   BooleanValue (true),
                   MakeBooleanAccessor (&RoutingProtocol::SetEtxEnable,
                                        &RoutingProtocol::GetEtxEnable),
                   MakeBooleanChecker ())
    .AddAttribute ("LppInterval", "Link probe packet emission interval.", //链路探测包发送间隔
                   TimeValue (Seconds (1)),
                   MakeTimeAccessor (&RoutingProtocol::m_lppInterval),
                   MakeTimeChecker ())
    .AddTraceSource ("Tx", "A new routing protocol packet is created and is sent", // trace
                     MakeTraceSourceAccessor (&RoutingProtocol::m_txTrace),
                     "ns3::Packet::TracedCallback")
  ;
  return tid;
}

这里的AddTraceSource函数增加了一个名为“Tx”的traceSource,用于描述一个路由协议数据包生成并且被传输,此时会调用m_txTrace函数。

  • 设置路由协议允许的缓冲队列长度
void
RoutingProtocol::SetMaxQueueLen (uint32_t len) //设置最大队列长度为64
{
   
  m_maxQueueLen = len;
  m_queue.SetMaxQueueLen (len);
}
  • 设置路由协议允许的缓冲一个数据包的最长时间
void
RoutingProtocol::SetMaxQueueTime (Time t) //设置最大队列时间30s
{
   
  m_maxQueueTime = t;
  m_queue.SetQueueTimeout (t);
}
  • 构造析构函数
RoutingProtocol::~RoutingProtocol ()
{
   
}
  • 声明dispose函数
void
RoutingProtocol::DoDispose ()
{
   
  m_ipv4 = 0;
  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter =
         m_socketAddresses.begin (); iter != m_socketAddresses.end (); iter++)
    {
   
      iter->first->Close ();
    }
  m_socketAddresses.clear (); //每个IP接口的原始单播套接字
  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter =
         m_socketSubnetBroadcastAddresses.begin (); iter != m_socketSubnetBroadcastAddresses.end (); iter++)
    {
   
      iter->first->Close ();
    }
  m_socketSubnetBroadcastAddresses.clear (); //每个IP接口的原始子网定向广播套接字
  Ipv4RoutingProtocol::DoDispose ();
}
  • 声明用于打印路由表的函数
void //打印路由表
RoutingProtocol::PrintRoutingTable (Ptr<OutputStreamWrapper> stream,Time::Unit unit) const
{
   
  *stream->GetStream () << "Node: " << m_ipv4->GetObject<Node> ()->GetId ()
                        << "; Time: " << Now().As (unit)
                        << ", Local time: " << GetObject<Node> ()->GetLocalTime ().As (unit)
                        << ", AODV Routing table" << std::endl;

  m_routingTable.Print (stream);
  *stream->GetStream () << std::endl;
}
  • 设置随机数序列
int64_t
RoutingProtocol::AssignStreams (int64_t stream) //为随机变量分配一个固定的随机数序列。并返回被分配的序列
{
   
  NS_LOG_FUNCTION (this << stream);
  m_uniformRandomVariable->SetStream (stream);
  return 1;
}
  • 设置start函数,开始路由操作
void
RoutingProtocol::Start () //开始路由操作
{
   
  NS_LOG_FUNCTION (this);
  if (m_enableHello)
    {
   
      m_nb.ScheduleTimer ();
    }
  m_rreqRateLimitTimer.SetFunction (&RoutingProtocol::RreqRateLimitTimerExpire, //重制RREQ计数并调度延迟1秒的RREQ限制计时器
                                    this);
  m_rreqRateLimitTimer.Schedule (Seconds (1));

  m_rerrRateLimitTimer.SetFunction (&RoutingProtocol::RerrRateLimitTimerExpire,//重制RERR计数并调度延迟1秒的RERR限制计时器
                                    this);
  m_rerrRateLimitTimer.Schedule (Seconds (1));
}
  • 设置路由输出函数
Ptr<Ipv4Route>
RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, //RouteOutput()在主动发包时调用,当找到路由时返回路由地址
                              Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
{
   
  NS_LOG_FUNCTION (this << header << (oif ? oif->GetIfIndex () : 0));
  if (!p)
    {
   
      NS_LOG_DEBUG("Packet is == 0");
      return LoopbackRoute (header, oif); // later
    }
  if (m_socketAddresses.empty ())
    {
   
      sockerr = Socket::ERROR_NOROUTETOHOST;
      NS_LOG_LOGIC ("No aodv interfaces");
      Ptr<Ipv4Route> route;
      return route;
    }
  sockerr = Socket::ERROR_NOTERROR;
  Ptr<Ipv4Route> route;
  Ipv4Address dst = header.GetDestination ();
  RoutingTableEntry rt;
  if (m_routingTable.LookupValidRoute (dst, rt))
    {
   
      route 
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值