详尽分析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), //指示只有目的节点才能回复RREQm_gratuitousReply (true), //指示一个RREP是否应该单播到发起路由发现的节点m_enableHello (false), //指示一个hello消息是否可行m_routingTable (m_deletePeriod), //路由表m_queue (m_maxQueueLen, m_maxQueueTime), //路由层缓存未找到路由的数据包时,采用drop-front队列m_requestId (0), //广播IDm_seqNo (0), //request序列号m_rreqIdCache (m_pathDiscoveryTime), //处理重复的RREQm_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 64MakeUintegerAccessor (&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", // traceMakeTraceSourceAccessor (&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 = rt.GetRoute ();NS_ASSERT (route != 0);NS_LOG_DEBUG ("Exist route to " << route->GetDestination () << " from interface " << route->GetSource ());if (oif != 0 && route->GetOutputDevice () != oif){NS_LOG_DEBUG ("Output device doesn't match. Dropped.");sockerr = Socket::ERROR_NOROUTETOHOST;return Ptr<Ipv4Route> ();}UpdateRouteLifeTime (dst, m_activeRouteTimeout);UpdateRouteLifeTime (route->GetGateway (), m_activeRouteTimeout);return route;}// Valid route not found, in this case we return loopback.没有找到有效的路由,此时返回loopback// Actual route request will be deferred until packet will be fully formed,实际路由请求将被延迟,直到数据包完全形成// routed to loopback, received from loopback and passed to RouteInput (see below)路由到环回,从环回接收并传递到RouteInputuint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1);DeferredRouteOutputTag tag (iif);NS_LOG_DEBUG ("Valid Route not found");if (!p->PeekPacketTag (tag)){p->AddPacketTag (tag);}return LoopbackRoute (header, oif);
}
  • 设置DeferredRouteOutput()函数
    用于发送RREQ消息
void
RoutingProtocol::DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header, //数据包排队并发送路由请求UnicastForwardCallback ucb, ErrorCallback ecb)
{NS_LOG_FUNCTION (this << p << header);NS_ASSERT (p != 0 && p != Ptr<Packet> ());QueueEntry newEntry (p, header, ucb, ecb);bool result = m_queue.Enqueue (newEntry);if (result){NS_LOG_LOGIC ("Add packet " << p->GetUid () << " to queue. Protocol " << (uint16_t) header.GetProtocol ());RoutingTableEntry rt;bool result = m_routingTable.LookupRoute (header.GetDestination (), rt);if(!result || ((rt.GetFlag () != IN_SEARCH) && result)){NS_LOG_LOGIC ("Send new RREQ for outbound packet to " <<header.GetDestination ());SendRequest (header.GetDestination ()); //发送RREQ}}
}
  • 设置路由输入函数RouteInput()
bool
RoutingProtocol::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, //RouteInput()收到包转发时调用的Ptr<const NetDevice> idev, UnicastForwardCallback ucb,MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
// Callback,回调函数就是通过函数指针调用的函数。
// 将函数的指针(地址)作为参数传递给另一个函数, 当指针被用来调用所指向函数时,即为回调函数
// 回调函数不是由函数的实现方直接调用,而是在特定时间发生时其他方调用,用于对该事件的响应
{NS_LOG_FUNCTION (this << p->GetUid () << header.GetDestination () << idev->GetAddress ());if (m_socketAddresses.empty ()){NS_LOG_LOGIC ("No aodv interfaces");return false;}NS_ASSERT (m_ipv4 != 0);NS_ASSERT (p != 0);// Check if input device supports IPNS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);int32_t iif = m_ipv4->GetInterfaceForDevice (idev);Ipv4Address dst = header.GetDestination ();Ipv4Address origin = header.GetSource ();// Deferred route request,延迟路由请求if (idev == m_lo){DeferredRouteOutputTag tag;if (p->PeekPacketTag (tag)){DeferredRouteOutput (p, header, ucb, ecb); //DeferredRouteOutput()会调用SendRequest来发送RREQreturn true;}}// Duplicate of own packet,自身数据包的副本if (IsMyOwnAddress (origin))return true;// AODV is not a multicast routing protocolif (dst.IsMulticast ()){return false;}// Broadcast local delivery/forwarding,广播本地传送/转发for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j){Ipv4InterfaceAddress iface = j->second;if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif)if (dst == iface.GetBroadcast () || dst.IsBroadcast ()){if (m_dpd.IsDuplicate (p, header)){NS_LOG_DEBUG ("Duplicated packet " << p->GetUid () << " from " << origin << ". Drop.");return true;}UpdateRouteLifeTime (origin, m_activeRouteTimeout);Ptr<Packet> packet = p->Copy ();if (lcb.IsNull () == false){NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ());lcb (p, header, iif);// Fall through to additional processing,过渡到附加处理}else{NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin);ecb (p, header, Socket::ERROR_NOROUTETOHOST);}if (!m_enableBroadcast){return true;}if (header.GetProtocol () == UdpL4Protocol::PROT_NUMBER){UdpHeader udpHeader;p->PeekHeader (udpHeader);if (udpHeader.GetDestinationPort () == AODV_PORT){// AODV packets sent in broadcast are already managed,广播中发送的AODV数据包已被管理return true;}}if (header.GetTtl () > 1){ // 转发广播NS_LOG_LOGIC ("Forward broadcast. TTL " << (uint16_t) header.GetTtl ());RoutingTableEntry toBroadcast;if (m_routingTable.LookupRoute (dst, toBroadcast)){Ptr<Ipv4Route> route = toBroadcast.GetRoute ();ucb (route, packet, header);}else{ // 没有路由转发广播,丢弃数据包NS_LOG_DEBUG ("No route to forward broadcast. Drop packet " << p->GetUid ());}}else{ // TTL超出,丢弃数据包NS_LOG_DEBUG ("TTL exceeded. Drop packet " << p->GetUid ());}return true;}}// Unicast local delivery 单播本地交付if (m_ipv4->IsDestinationAddress (dst, iif)){UpdateRouteLifeTime (origin, m_activeRouteTimeout);RoutingTableEntry toOrigin;if (m_routingTable.LookupValidRoute (origin, toOrigin)){UpdateRouteLifeTime (toOrigin.GetNextHop (), m_activeRouteTimeout);m_nb.Update (toOrigin.GetNextHop (), m_activeRouteTimeout);}if (lcb.IsNull () == false){ // 单播本地交付到dstNS_LOG_LOGIC ("Unicast local delivery to " << dst);lcb (p, header, iif);}else{ // 由于null回调,无法在本地交付数据包NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin);ecb (p, header, Socket::ERROR_NOROUTETOHOST);}return true;}// Check if input device supports IP forwarding 检查设备是否支持IP转发if (m_ipv4->IsForwarding (iif) == false){NS_LOG_LOGIC ("Forwarding disabled for this interface");ecb (p, header, Socket::ERROR_NOROUTETOHOST);return true;}// Forwardingreturn Forwarding (p, header, ucb, ecb);
}
  • 设置前向转发函数Forwarding()
    用于转发数据包
bool
RoutingProtocol::Forwarding (Ptr<const Packet> p, const Ipv4Header & header, //当路由存在且有效时,调用Forwarding()函数传输数据包UnicastForwardCallback ucb, ErrorCallback ecb)
{NS_LOG_FUNCTION (this);Ipv4Address dst = header.GetDestination ();Ipv4Address origin = header.GetSource ();m_routingTable.Purge ();RoutingTableEntry toDst;if (m_routingTable.LookupRoute (dst, toDst)){if (toDst.GetFlag () == VALID){Ptr<Ipv4Route> route = toDst.GetRoute ();NS_LOG_LOGIC (route->GetSource ()<<" forwarding to " << dst << " from " << origin << " packet " << p->GetUid ());/**  Each time a route is used to forward a data packet, its Active Route*  Lifetime field of the source, destination and the next hop on the*  path to the destination is updated to be no less than the current*  time plus ActiveRouteTimeout.* 每次使用路由转发数据包时,其源、目标和目标路径上下一跃点的Active route Lifetime字段将更新为不小于当前时间加上ActiveRouteTimeout。*/UpdateRouteLifeTime (origin, m_activeRouteTimeout);UpdateRouteLifeTime (dst, m_activeRouteTimeout);UpdateRouteLifeTime (route->GetGateway (), m_activeRouteTimeout);/**  Since the route between each originator and destination pair is expected to be symmetric, the*  Active Route Lifetime for the previous hop, along the reverse path back to the IP source, is also updated*  to be no less than the current time plus ActiveRouteTimeout* 由于每个始发方和目标对之间的路由预期是对称的,因此上一跳的活动路由生存期(沿着返回IP源的反向路径)也会更新为不小于当前时间加上ActiveRouteTimeout*/RoutingTableEntry toOrigin;m_routingTable.LookupRoute (origin, toOrigin);UpdateRouteLifeTime (toOrigin.GetNextHop (), m_activeRouteTimeout);m_nb.Update (route->GetGateway (), m_activeRouteTimeout);m_nb.Update (toOrigin.GetNextHop (), m_activeRouteTimeout);ucb (route, p, header);return true;}else{if (toDst.GetValidSeqNo ()){SendRerrWhenNoRouteToForward (dst, toDst.GetSeqNo (), origin);NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");return false;}}}NS_LOG_LOGIC ("route not found to "<< dst << ". Send RERR message.");NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");SendRerrWhenNoRouteToForward (dst, 0, origin);return false;
}
  • 设置SetIpv4()函数
    应该是根据给定的IPv4地址,寻找合适的环回路由并记录在路由表中
void
RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4)
{NS_ASSERT (ipv4 != 0);NS_ASSERT (m_ipv4 == 0);m_ipv4 = ipv4;// Create lo route. It is asserted that the only one interface up for now is loopbackNS_ASSERT (m_ipv4->GetNInterfaces () == 1 && m_ipv4->GetAddress (0, 0).GetLocal () == Ipv4Address ("127.0.0.1"));m_lo = m_ipv4->GetNetDevice (0);NS_ASSERT (m_lo != 0);// Remember lo routeRoutingTableEntry rt (/*device=*/ m_lo, /*dst=*/ Ipv4Address::GetLoopback (), /*know seqno=*/ true, /*seqno=*/ 0,/*iface=*/ Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask ("255.0.0.0")),/*hops=*/ 1, /*next hop=*/ Ipv4Address::GetLoopback (),/*lifetime=*/ Simulator::GetMaximumSimulationTime ());m_routingTable.AddRoute (rt); //若当前路由条目不在路由表中,则在路由表中增加相应的条目Simulator::ScheduleNow (&RoutingProtocol::Start, this);
}
  • 设置NotifyInterfaceUp()函数
    创建相应的套接字监听接口
void
RoutingProtocol::NotifyInterfaceUp (uint32_t i)
{NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();if (l3->GetNAddresses (i) > 1){NS_LOG_WARN ("AODV does not work with more then one address per each interface.");}Ipv4InterfaceAddress iface = l3->GetAddress (i, 0);if (iface.GetLocal () == Ipv4Address ("127.0.0.1"))return;// Create a socket to listen only on this interface创建套接字以仅侦听此接口Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());NS_ASSERT (socket != 0);socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvAodv, this));socket->BindToNetDevice (l3->GetNetDevice (i));socket->Bind (InetSocketAddress (iface.GetLocal (), AODV_PORT));socket->SetAllowBroadcast (true);socket->SetIpRecvTtl (true);m_socketAddresses.insert (std::make_pair (socket, iface));// create also a subnet broadcast socketsocket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());NS_ASSERT (socket != 0);socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvAodv, this));socket->BindToNetDevice (l3->GetNetDevice (i));socket->Bind (InetSocketAddress (iface.GetBroadcast (), AODV_PORT));socket->SetAllowBroadcast (true);socket->SetIpRecvTtl (true);m_socketSubnetBroadcastAddresses.insert (std::make_pair (socket, iface));// Add local broadcast record to the routing tablePtr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()));RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, /*seqno=*/ 0, /*iface=*/ iface,/*hops=*/ 1, /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());m_routingTable.AddRoute (rt);if (l3->GetInterface (i)->GetArpCache ()){m_nb.AddArpCache (l3->GetInterface (i)->GetArpCache ());}// Allow neighbor manager use this interface for layer 2 feedback if possiblePtr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();if (wifi == 0)return;Ptr<WifiMac> mac = wifi->GetMac ();if (mac == 0)return;mac->TraceConnectWithoutContext ("TxErrHeader", m_nb.GetTxErrorCallback ());
}
  • 设置NotifyInterfaceDown()函数
    取消监听,关闭套接字
void
RoutingProtocol::NotifyInterfaceDown (uint32_t i)
{NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());// Disable layer 2 link state monitoring (if possible)Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();Ptr<NetDevice> dev = l3->GetNetDevice (i);Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();if (wifi != 0){Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> ();if (mac != 0){mac->TraceDisconnectWithoutContext ("TxErrHeader",m_nb.GetTxErrorCallback ());m_nb.DelArpCache (l3->GetInterface (i)->GetArpCache ());}}// Close socketPtr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0));NS_ASSERT (socket);socket->Close ();m_socketAddresses.erase (socket);// Close socketsocket = FindSubnetBroadcastSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0));NS_ASSERT (socket);socket->Close ();m_socketSubnetBroadcastAddresses.erase (socket);if (m_socketAddresses.empty ()){NS_LOG_LOGIC ("No aodv interfaces");m_htimer.Cancel ();m_nb.Clear ();m_routingTable.Clear ();return;}m_routingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i, 0));
}
  • 设置IsMyOwnAddress()函数
    测试提供的地址是否分配给该节点上的接口
bool
RoutingProtocol::titi sh (Ipv4Address src) //测试提供的地址是否分配给该节点上的接口
{NS_LOG_FUNCTION (this << src);for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j){Ipv4InterfaceAddress iface = j->second;if (src == iface.GetLocal ()){return true;}}return false;
}
  • 设置LoopbackRoute()函数
    对于给定的header,生成环回路由
Ptr<Ipv4Route>
RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr, Ptr<NetDevice> oif) const //对于给定的header,生成环回路由
{NS_LOG_FUNCTION (this << hdr);NS_ASSERT (m_lo != 0);Ptr<Ipv4Route> rt = Create<Ipv4Route> ();rt->SetDestination (hdr.GetDestination ());//// Source address selection here is tricky.  The loopback route is// returned when AODV does not have a route; this causes the packet// to be looped back and handled (cached) in RouteInput() method// while a route is found. However, connection-oriented protocols// like TCP need to create an endpoint four-tuple (src, src port,// dst, dst port) and create a pseudo-header for checksumming.  So,// AODV needs to guess correctly what the eventual source address// will be.//// For single interface, single address nodes, this is not a problem.// When there are possibly multiple outgoing interfaces, the policy// implemented here is to pick the first available AODV interface.// If RouteOutput() caller specified an outgoing interface, that// further constrains the selection of source address//std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin ();if (oif){// Iterate to find an address on the oif devicefor (j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j){Ipv4Address addr = j->second.GetLocal ();int32_t interface = m_ipv4->GetInterfaceForAddress (addr);if (oif == m_ipv4->GetNetDevice (static_cast<uint32_t> (interface))){rt->SetSource (addr);break;}}}else{rt->SetSource (j->second.GetLocal ());}NS_ASSERT_MSG (rt->GetSource () != Ipv4Address (), "Valid AODV source address not found");rt->SetGateway (Ipv4Address ("127.0.0.1"));rt->SetOutputDevice (m_lo);return rt;
}
  • 设置函数
    用于发送RREQ消息
void
RoutingProtocol::SendRequest (Ipv4Address dst) //发送RREQ消息
{NS_LOG_FUNCTION ( this << dst);// A node SHOULD NOT originate more than RREQ_RATELIMIT RREQ messages per second.if (m_rreqCount == m_rreqRateLimit){Simulator::Schedule (m_rreqRateLimitTimer.GetDelayLeft () + MicroSeconds (100),&RoutingProtocol::SendRequest, this, dst);return;}elsem_rreqCount++;// Create RREQ headerRreqHeader rreqHeader;rreqHeader.SetDst (dst);RoutingTableEntry rt;// Using the Hop field in Routing Table to manage the expanding ring searchuint16_t ttl = m_ttlStart;if (m_routingTable.LookupRoute (dst, rt)){if (rt.GetFlag () != IN_SEARCH){ttl = std::min<uint16_t> (rt.GetHop () + m_ttlIncrement, m_netDiameter);}else{ttl = rt.GetHop () + m_ttlIncrement;if (ttl > m_ttlThreshold)ttl = m_netDiameter;}if (ttl == m_netDiameter)rt.IncrementRreqCnt ();if (rt.GetValidSeqNo ())rreqHeader.SetDstSeqno (rt.GetSeqNo ());elserreqHeader.SetUnknownSeqno (true);rt.SetHop (ttl);rt.SetFlag (IN_SEARCH);rt.SetLifeTime (m_pathDiscoveryTime);m_routingTable.Update (rt);}else{rreqHeader.SetUnknownSeqno (true);Ptr<NetDevice> dev = 0;RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ false, /*seqno=*/ 0,/*iface=*/ Ipv4InterfaceAddress (),/*hop=*/ ttl,/*nextHop=*/ Ipv4Address (), /*lifeTime=*/ m_pathDiscoveryTime, /*etx*/ 0);// Check if TtlStart == NetDiameterif (ttl == m_netDiameter)newEntry.IncrementRreqCnt ();newEntry.SetFlag (IN_SEARCH);m_routingTable.AddRoute (newEntry);}if (m_gratuitousReply)rreqHeader.SetGratuitousRrep (true);if (m_destinationOnly)rreqHeader.SetDestinationOnly (true);m_seqNo++;rreqHeader.SetOriginSeqno (m_seqNo);m_requestId++;rreqHeader.SetId (m_requestId);// Send RREQ as subnet directed broadcast from each interface used by aodvfor (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j){Ptr<Socket> socket = j->first;Ipv4InterfaceAddress iface = j->second;rreqHeader.SetOrigin (iface.GetLocal ());m_rreqIdCache.IsDuplicate (iface.GetLocal (), m_requestId);Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag tag;tag.SetTtl (ttl);packet->AddPacketTag (tag);packet->AddHeader (rreqHeader);TypeHeader tHeader (AODVTYPE_RREQ);packet->AddHeader (tHeader);// Send to all-hosts broadcast if on /32 addr, subnet-directed otherwiseIpv4Address destination;if (iface.GetMask () == Ipv4Mask::GetOnes ()){destination = Ipv4Address ("255.255.255.255");}else{destination = iface.GetBroadcast ();}NS_LOG_DEBUG ("Send RREQ: " << iface.GetLocal () << " --> " << destination << " for dst " << dst << " ID" << m_requestId << " SeqNo " << m_seqNo);NS_LOG_DEBUG ("Send RREQ with id " << rreqHeader.GetId () << " to socket");m_lastBcastTime = Simulator::Now ();Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);}ScheduleRreqRetry (dst);
}
  • 设置SendTo()函数
    向目的地套接字发送数据包
void
RoutingProtocol::SendTo (Ptr<Socket> socket, Ptr<Packet> packet, Ipv4Address destination) //向目的地套接字发送数据包
{socket->SendTo (packet, 0, InetSocketAddress (destination, AODV_PORT));m_txTrace (packet); // trace
}
  • 设置ScheduleRreqRetry()函数
    对于单个目的节点,源节点在路由发现过程中使用扩展环搜索技术反复尝试找到有效路由
void
RoutingProtocol::ScheduleRreqRetry (Ipv4Address dst)
{NS_LOG_FUNCTION (this << dst);if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ()){Timer timer (Timer::CANCEL_ON_DESTROY);m_addressReqTimer[dst] = timer;}m_addressReqTimer[dst].SetFunction (&RoutingProtocol::RouteRequestTimerExpire, this);m_addressReqTimer[dst].Remove ();m_addressReqTimer[dst].SetArguments (dst);RoutingTableEntry rt;m_routingTable.LookupRoute (dst, rt);Time retry;if (rt.GetHop () < m_netDiameter){retry = 2 * m_nodeTraversalTime * (rt.GetHop () + m_timeoutBuffer);}else{// Binary exponential backoffretry = std::pow<uint16_t> (2, rt.GetRreqCnt () - 1) * m_netTraversalTime;}m_addressReqTimer[dst].Schedule (retry);NS_LOG_LOGIC ("Scheduled RREQ retry in " << retry.GetSeconds () << " seconds");
}
  • 设置RecvAodv()函数
    当接收到一个aodv数据包时,需要具体判断具体是哪种类型的数据包,根据类型进行不同的操作
void
RoutingProtocol::RecvAodv (Ptr<Socket> socket) //若数据包是aodv包,则调用RecvAodv()函数
{NS_LOG_FUNCTION (this << socket);// Get source address (this is neighbor's IP) and packet from socketAddress sourceAddress;Ptr<Packet> packet = socket->RecvFrom (sourceAddress);InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);Ipv4Address sender = inetSourceAddr.GetIpv4 ();// Get reciver address from socket, this is my IPIpv4Address receiver;if (m_socketAddresses.find (socket) != m_socketAddresses.end ()){receiver = m_socketAddresses[socket].GetLocal ();}else if(m_socketSubnetBroadcastAddresses.find (socket) != m_socketSubnetBroadcastAddresses.end ()){receiver = m_socketSubnetBroadcastAddresses[socket].GetLocal ();}else{NS_ASSERT_MSG (false, "Received a packet from an unknown socket");}NS_LOG_DEBUG ("AODV node " << this << " received a AODV packet from " << sender << " to " << receiver);// Add new or update existing route to neighbor (but be aware that there is no valid seq no. at this point!)// Update route with new etx valueUpdateRouteToNeighbor (sender, receiver);TypeHeader tHeader (AODVTYPE_RREQ);packet->RemoveHeader (tHeader);if (!tHeader.IsValid ()){NS_LOG_DEBUG ("AODV message " << packet->GetUid () << " with unknown type received: " << tHeader.Get () << ". Drop");return; // drop}switch (tHeader.Get ()) //接收到一个AODV数据包,开始判断数据包类型{case AODVTYPE_RREQ: //路由请求数据包{RecvRequest (packet, receiver, sender); //接收到RREQ数据包,调用RecvRequest()函数break;}case AODVTYPE_RREP: //路由响应数据包{RecvReply (packet, receiver, sender); //接收到RREP数据包,调用RecvReply()函数break;}case AODVTYPE_RERR: //路由错误数据包{RecvError (packet, sender); //接收到RERR数据包,调用RecvError()函数break;}case AODVTYPE_RREP_ACK: //RREP回复数据包{RecvReplyAck (sender); //接收到RREP-ACK数据包,调用RecvReplyAck()函数break;}case AODVTYPE_LPP: //LPP数据包(探测链路质量ETX){RecvLpp (packet, receiver, sender); //接收到LPP数据包,调用RecvLpp()函数break;}}
}
  • 设置UpdateRouteLifeTime()函数
    当路由条目存在时,将路由条目中的生存时间设置为现有的生存时间最大值
bool
RoutingProtocol::UpdateRouteLifeTime (Ipv4Address addr, Time lifetime)
{NS_LOG_FUNCTION (this << addr << lifetime);RoutingTableEntry rt;if (m_routingTable.LookupRoute (addr, rt)){if (rt.GetFlag () == VALID){NS_LOG_DEBUG ("Updating VALID route");rt.SetRreqCnt (0);rt.SetLifeTime (std::max (lifetime, rt.GetLifeTime ()));m_routingTable.Update (rt);return true;}}return false;
}
  • 设置UpdateRouteToNeighbor()函数
    向邻居更新路由
void
RoutingProtocol::UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver)
{NS_LOG_FUNCTION (this << "sender " << sender << " receiver " << receiver);RoutingTableEntry toNeighbor;if (!m_routingTable.LookupRoute (sender, toNeighbor)){Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));// Cannot update seqno in this phase (it will be updated later)RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0,/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hops=*/ 1, /*next hop=*/ sender, /*lifetime=*/ m_activeRouteTimeout,/*etx*/ m_nbEtx.GetEtxForNeighbor (sender));m_routingTable.AddRoute (newEntry);}else{Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));if (toNeighbor.GetValidSeqNo () && (toNeighbor.GetHop () == 1) && (toNeighbor.GetOutputDevice () == dev)){toNeighbor.SetLifeTime (std::max (m_activeRouteTimeout, toNeighbor.GetLifeTime ()));toNeighbor.SetEtx (m_nbEtx.GetEtxForNeighbor (sender));m_routingTable.Update (toNeighbor); // this was missing in original AODV inplementation}else{// Cannot update seqno in this phase (it will be updated later)RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0,/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hops=*/ 1, /*next hop=*/ sender,/*lifetime=*/ std::max (m_activeRouteTimeout, toNeighbor.GetLifeTime ()),/*etx*/ m_nbEtx.GetEtxForNeighbor (sender));m_routingTable.Update (newEntry);}}
}
  • 设置RecvLpp()函数
    接收到Lpp数据包之后进行的操作
void
RoutingProtocol::RecvLpp (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src)
{NS_LOG_FUNCTION (this);//NS_LOG_DEBUG ("LPP receive: " << Simulator::Now ().GetSeconds () << " - sender = " << src << ", receiver = " << receiver);LppHeader lppHeader;p->RemoveHeader (lppHeader);Ipv4Address origin = lppHeader.GetOriginAddress ();NS_ASSERT (origin == src); // Neighbor from which the packet is received is always originator of LPP packetuint8_t lppTimeStamp = lppHeader.GetLppId ();uint16_t numNeighbors = lppHeader.GetNumberNeighbors ();std::pair<Ipv4Address, uint8_t> un;// Search for my IP address in LPP packet headeruint8_t lppReverse = 0; // if there is no my address in the packet header lpp reverse should be 0for (uint16_t j=0; j<numNeighbors; ++j){lppHeader.RemoveFromNeighborsList (un);if (un.first == receiver) // is it my IP address?{lppReverse = un.second;break;}}// Add new or udate existing etx entry for neighbor with IP address "src".// LPP count is updated based on lppTime stamp received in packet header.// LPP reverse count is updated from list provided in LPP packet header.m_nbEtx.UpdateNeighborEtx (src, lppTimeStamp, lppReverse);// Since ETX is changed we should udate route entry for neighbor// LPP is used as HELLO so it should be updateted as if HELLO message is received// Use LPP as HELLO message, so do the same as ProcessHello (), but use ETX metrixRoutingTableEntry toNeighbor;if (!m_routingTable.LookupRoute (src, toNeighbor)){Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ src, /*validSeqNo=*/ true,/*seqno=*/ lppHeader.GetOriginSeqno (),/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/ 1, /*nextHop=*/ src,/*lifeTime=*/ Time (m_allowedHelloLoss * m_helloInterval),/*etx*/ m_nbEtx.GetEtxForNeighbor (src));m_routingTable.AddRoute (newEntry);}else{toNeighbor.SetLifeTime (std::max (Time (m_allowedHelloLoss * m_helloInterval), toNeighbor.GetLifeTime ()));toNeighbor.SetSeqNo (lppHeader.GetOriginSeqno ());toNeighbor.SetValidSeqNo (true);toNeighbor.SetFlag (VALID);toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));toNeighbor.SetHop (1);toNeighbor.SetNextHop (src);toNeighbor.SetEtx (m_nbEtx.GetEtxForNeighbor (src));m_routingTable.Update (toNeighbor);}m_nb.Update (src, Time (m_allowedHelloLoss * m_helloInterval));
}
  • 设置RecvRequest()函数
    接收到RREQ消息后进行的操作
void
RoutingProtocol::RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src)
// src is neigbor's IP
{NS_LOG_FUNCTION (this);RreqHeader rreqHeader;p->RemoveHeader (rreqHeader);// A node ignores all RREQs received from any node in its blacklistRoutingTableEntry toPrev;if (m_routingTable.LookupRoute (src, toPrev)){if (toPrev.IsUnidirectional ()){NS_LOG_DEBUG ("Ignoring RREQ from node in blacklist");return;}}uint32_t id = rreqHeader.GetId ();Ipv4Address origin = rreqHeader.GetOrigin (); // Originator is not always neighbor (RREQ forwarding)NS_LOG_DEBUG ("Recv RREQ [ID=" << rreqHeader.GetId () << ",OriginSeqNo=" << rreqHeader.GetOriginSeqno () << "]: " << src << " --> " << receiver << ", originator " << origin << " dst " << rreqHeader.GetDst ());// Increment RREQ hop countuint8_t hop = rreqHeader.GetHopCount () + 1;rreqHeader.SetHopCount (hop);// Add in RREQ ETX metrix for last hop from neighbor to this node// Now RREQ contains ETX from origin to this nodeuint32_t etx = m_nbEtx.GetEtxForNeighbor (src); // src is always neighbor, origin maybe isn'tif (etx == NeighborEtx::EtxMaxValue ()){ // this should never happen because neighbor has limited ETX, but it is better to check!NS_LOG_DEBUG ("ETX -> oo !!! ");rreqHeader.SetEtx (etx);}else{rreqHeader.SetEtx (etx + rreqHeader.GetEtx ());}NS_LOG_DEBUG ("Recv RREQ header: hop " << int(hop) << ", ETX " << rreqHeader.GetEtx ());/**  Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID.*  If such a RREQ has been received, the node silently discards the newly received RREQ.*  This is modified to include ETX, so RREQ is discarded only if etx of previously received RREQ is beter (smaller) then this one*/if (m_rreqIdCache.IsDuplicate (origin, id)){RoutingTableEntry rte;if (m_routingTable.LookupRoute (origin, rte)){if (rte.GetEtx () <= rreqHeader.GetEtx ()){NS_LOG_DEBUG ("Ignoring RREQ due to duplicate, previous RREQ had better ETX.");NS_LOG_DEBUG ("Duplicate, IGNORE previous RREQ had better ETX.");return;}NS_LOG_DEBUG ("Duplicate, but better ETX. Continue...");}NS_LOG_DEBUG ("Duplicate, but no route in the table. Continue...");}elseNS_LOG_DEBUG ("Not found duplicate. Continue...");// This should be solved by previous if due to duplicate RREQ, but it is not?!if (receiver == rreqHeader.GetOrigin ()){NS_LOG_DEBUG ("This is my own RREQ, so drop!");return;}/**  When the reverse route is created or updated, the following actions on the route are also carried out:*  1. the Originator Sequence Number from the RREQ is compared to the corresponding destination sequence number*     in the route table entry and copied if greater than the existing value there*  2. the valid sequence number field is set to true;*  3. the next hop in the routing table becomes the node from which the  RREQ was received*  4. the hop count is copied from the Hop Count in the RREQ message;*  5. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where*     MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime*  6. ETX is copied from the RREQ message*/RoutingTableEntry toOrigin;if (!m_routingTable.LookupRoute (origin, toOrigin)){ // There is no route in the routing tablePtr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ origin, /*validSeno=*/ true, /*seqNo=*/ rreqHeader.GetOriginSeqno (),/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), /*hops=*/ hop,/*nextHop*/ src, /*timeLife=*/ Time ((2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime)),/*etx*/ rreqHeader.GetEtx ());m_routingTable.AddRoute (newEntry);}else{ // Update existing routeif (toOrigin.GetValidSeqNo ()){if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0)toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); // update sequence number with newer one}elsetoOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ());toOrigin.SetValidSeqNo (true);toOrigin.SetNextHop (src);toOrigin.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));toOrigin.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));toOrigin.SetHop (hop);toOrigin.SetLifeTime (std::max (Time (2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime),toOrigin.GetLifeTime ()));toOrigin.SetEtx (rreqHeader.GetEtx ());m_routingTable.Update (toOrigin);}RoutingTableEntry toNeighbor;if (!m_routingTable.LookupRoute (src, toNeighbor)){ // Nenad: No rute in routing table, this should never happen since the route for neighbor is created in RecvAodv ()NS_LOG_DEBUG ("Neighbor:" << src << " not found in routing table. Creating an entry");Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));RoutingTableEntry newEntry (dev, src, false, rreqHeader.GetOriginSeqno (), /* Nenad: not clear to me why seqno is not valid? */m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),1, src, m_activeRouteTimeout,/*etx*/ m_nbEtx.GetEtxForNeighbor (src));m_routingTable.AddRoute (newEntry);}else{ // Update existing routetoNeighbor.SetLifeTime (m_activeRouteTimeout);toNeighbor.SetValidSeqNo (false); // Nenad: not clear to me why seqno is not valid?toNeighbor.SetSeqNo (rreqHeader.GetOriginSeqno ());toNeighbor.SetFlag (VALID);toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));toNeighbor.SetHop (1);toNeighbor.SetNextHop (src);toNeighbor.SetEtx (m_nbEtx.GetEtxForNeighbor (src));m_routingTable.Update (toNeighbor);}// Update neighborsm_nb.Update (src, Time (m_allowedHelloLoss * m_helloInterval));NS_LOG_LOGIC (receiver << " receive RREQ with hop count " << static_cast<uint32_t>(rreqHeader.GetHopCount ())<< " ID " << rreqHeader.GetId ()<< " to destination " << rreqHeader.GetDst ());//  A node generates a RREP if either://  (i)  it is itself the destination,if (IsMyOwnAddress (rreqHeader.GetDst ())){m_routingTable.LookupRoute (origin, toOrigin);NS_LOG_DEBUG ("Send reply since I am the destination");SendReply (rreqHeader, toOrigin);return;}/** (ii) or it has an active route to the destination, the destination sequence number in the node's existing route table entry for the destination*      is valid and greater than or equal to the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set.*/RoutingTableEntry toDst;Ipv4Address dst = rreqHeader.GetDst ();if (m_routingTable.LookupRoute (dst, toDst)){/** Drop RREQ, This node RREP wil make a loop.*/if (toDst.GetNextHop () == src){NS_LOG_DEBUG ("Drop RREQ from " << src << ", dest next hop " << toDst.GetNextHop ());return;}/** The Destination Sequence number for the requested destination is set to the maximum of the corresponding value* received in the RREQ message, and the destination sequence value currently maintained by the node for the requested destination.* However, the forwarding node MUST NOT modify its maintained value for the destination sequence number, even if the value* received in the incoming RREQ is larger than the value currently maintained by the forwarding node.*/if ((rreqHeader.GetUnknownSeqno () || (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) >= 0))&& toDst.GetValidSeqNo () ){if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag () == VALID){m_routingTable.LookupRoute (origin, toOrigin);SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratuitousRrep ());return;}// Update seqno and valid fileds in the RREQ packet for forwardingrreqHeader.SetDstSeqno (toDst.GetSeqNo ());rreqHeader.SetUnknownSeqno (false);}}// Forward RREQSocketIpTtlTag tag;p->RemovePacketTag (tag);if (tag.GetTtl () < 2){NS_LOG_DEBUG ("TTL exceeded. Drop RREQ origin " << src << " destination " << dst );return;}for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j){Ptr<Socket> socket = j->first;Ipv4InterfaceAddress iface = j->second;Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag ttl;ttl.SetTtl (tag.GetTtl () - 1);packet->AddPacketTag (ttl);packet->AddHeader (rreqHeader);TypeHeader tHeader (AODVTYPE_RREQ);packet->AddHeader (tHeader);// Send to all-hosts broadcast if on /32 addr, subnet-directed otherwiseIpv4Address destination;if (iface.GetMask () == Ipv4Mask::GetOnes ()){destination = Ipv4Address ("255.255.255.255");}else{destination = iface.GetBroadcast ();}m_lastBcastTime = Simulator::Now ();Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);}
}
  • 设置SendReplyAck()函数
    用于发送RREP_ACK
void
RoutingProtocol::SendReplyAck (Ipv4Address neighbor)
{NS_LOG_FUNCTION (this << " to " << neighbor);RrepAckHeader h;TypeHeader typeHeader (AODVTYPE_RREP_ACK);Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag tag;tag.SetTtl (1);packet->AddPacketTag (tag);packet->AddHeader (h);packet->AddHeader (typeHeader);RoutingTableEntry toNeighbor;m_routingTable.LookupRoute (neighbor, toNeighbor);Ptr<Socket> socket = FindSocketWithInterfaceAddress (toNeighbor.GetInterface ());NS_ASSERT (socket);socket->SendTo (packet, 0, InetSocketAddress (neighbor, AODV_PORT));m_txTrace (packet); // trace
}
  • 设置RecvReply()函数
    接收RREP消息后进行的操作
void
RoutingProtocol::RecvReply (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address sender)
{NS_LOG_FUNCTION (this << " src " << sender);RrepHeader rrepHeader;p->RemoveHeader (rrepHeader);Ipv4Address dst = rrepHeader.GetDst ();NS_LOG_LOGIC ("RREP destination " << dst << " RREP origin " << rrepHeader.GetOrigin ());uint8_t hop = rrepHeader.GetHopCount () + 1;rrepHeader.SetHopCount (hop);// If RREP is Hello messageif (dst == rrepHeader.GetOrigin ()){ProcessHello (rrepHeader, receiver);return;}// Add in RREP header ETX metrix for last hop from neighbor to this node// Now RREP contains ETX from destination to this nodeuint32_t etx = m_nbEtx.GetEtxForNeighbor (sender); // sender is always neighbor, destination maybe isn'tif (etx == NeighborEtx::EtxMaxValue ()){ // this should never happen because neighbor has limited ETX, but it is better to check!NS_LOG_DEBUG ("ETX -> oo !!! ");rrepHeader.SetEtx (etx);}else{rrepHeader.SetEtx (etx + rrepHeader.GetEtx ());}// For testingNS_LOG_DEBUG ("RREP: " << Simulator::Now ().GetSeconds () << " sec.");NS_LOG_DEBUG ("      " << dst << "-->" << sender << " --> " << receiver << " --> " << rrepHeader.GetOrigin ());NS_LOG_DEBUG ("      hops: " << int(hop) << ", ETX: " << rrepHeader.GetEtx ());if (receiver == rrepHeader.GetOrigin ()){//NS_LOG_DEBUG ("      ROUTE FOUND!");}/** If the route table entry to the destination is created or updated, then the following actions occur:* -  the route is marked as active,* -  the destination sequence number is marked as valid,* -  the next hop in the route entry is assigned to be the node from which the RREP is received,*    which is indicated by the source IP address field in the IP header,* -  the hop count is set to the value of the hop count from RREP message + 1* -  the expiry time is set to the current time plus the value of the Lifetime in the RREP message,* -  etx is used from the RREP message,* -  and the destination sequence number is the Destination Sequence Number in the RREP message.*/Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (),/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/ hop,/*nextHop=*/ sender, /*lifeTime=*/ rrepHeader.GetLifeTime (),/*etx*/ rrepHeader.GetEtx ());RoutingTableEntry toDst;if (m_routingTable.LookupRoute (dst, toDst)){/** The existing entry is updated only in the following circumstances:* (i) the sequence number in the routing table is marked as invalid in route table entry.*/if (!toDst.GetValidSeqNo ()){m_routingTable.Update (newEntry);NS_LOG_DEBUG ("      Route updated: the sequence number in the routing table is marked as invalid in route table entry.");}// (ii)the Destination Sequence Number in the RREP is greater than the node's copy of the destination sequence number and the known value is valid,else if ((int32_t (rrepHeader.GetDstSeqno ()) - int32_t (toDst.GetSeqNo ())) > 0){m_routingTable.Update (newEntry);NS_LOG_DEBUG ("      Route updated: the Destination Sequence Number in the RREP is greater than the node's copy of the destination sequence number and the known value is valid.");}else if (rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()){// (iii) the sequence numbers are the same, but the route is marked as inactive.if (toDst.GetFlag () != VALID){m_routingTable.Update (newEntry);NS_LOG_DEBUG ("      Route updated: the sequence numbers are the same, but the route is marked as inactive.");}// (iv) the sequence numbers are the same, but ETX is smallerelse if (rrepHeader.GetEtx () < toDst.GetEtx ()){m_routingTable.Update (newEntry);NS_LOG_DEBUG ("      Route updated: the sequence numbers are the same, but ETX is smaller.");}// (v)  the sequence numbers and ETX are the same, and the New Hop Count is smaller than the hop count in route table entry.else if ((rrepHeader.GetEtx () == toDst.GetEtx ()) && (hop < toDst.GetHop ())){m_routingTable.Update (newEntry);NS_LOG_DEBUG ("      Route updated: the sequence numbers and ETX are the same, and the New Hop Count is smaller than the hop count in route table entry.");}
/*// Nenad: Should lifetime of active route from table be updated if new route is equal to existing one?else if ((rrepHeader.GetDstSeqno () == toDst.GetEtx ()) && (hop == toDst.GetHop ())){toDst.SetLifeTime (std::max (rrepHeader.GetLifeTime (), toDst.GetLifeTime ()));m_routingTable.Update (toDst);}
*/}}else{// The forward route for this destination is created if it does not already exist.NS_LOG_LOGIC ("add new route");m_routingTable.AddRoute (newEntry);NS_LOG_DEBUG ("      Add new route.");}// Acknowledge receipt of the RREP by sending a RREP-ACK message backif (rrepHeader.GetAckRequired ()){SendReplyAck (sender);rrepHeader.SetAckRequired (false);}NS_LOG_LOGIC ("receiver " << receiver << " origin " << rrepHeader.GetOrigin ());if (IsMyOwnAddress (rrepHeader.GetOrigin ())){if (toDst.GetFlag () == IN_SEARCH){m_routingTable.Update (newEntry);m_addressReqTimer[dst].Remove ();m_addressReqTimer.erase (dst);}m_routingTable.LookupRoute (dst, toDst);SendPacketFromQueue (dst, toDst.GetRoute ());NS_LOG_DEBUG ("      ROUTE FOUND!");return;}RoutingTableEntry toOrigin;if (!m_routingTable.LookupRoute (rrepHeader.GetOrigin (), toOrigin) || toOrigin.GetFlag () == IN_SEARCH){return; // Impossible! drop.}toOrigin.SetLifeTime (std::max (m_activeRouteTimeout, toOrigin.GetLifeTime ()));m_routingTable.Update (toOrigin);// Update information about precursorsif (m_routingTable.LookupValidRoute (rrepHeader.GetDst (), toDst)){toDst.InsertPrecursor (toOrigin.GetNextHop ());m_routingTable.Update (toDst);RoutingTableEntry toNextHopToDst;m_routingTable.LookupRoute (toDst.GetNextHop (), toNextHopToDst);toNextHopToDst.InsertPrecursor (toOrigin.GetNextHop ());m_routingTable.Update (toNextHopToDst);toOrigin.InsertPrecursor (toDst.GetNextHop ());m_routingTable.Update (toOrigin);RoutingTableEntry toNextHopToOrigin;m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHopToOrigin);toNextHopToOrigin.InsertPrecursor (toDst.GetNextHop ());m_routingTable.Update (toNextHopToOrigin);}SocketIpTtlTag tag;p->RemovePacketTag(tag);if (tag.GetTtl () < 2){NS_LOG_DEBUG ("TTL exceeded. Drop RREP destination " << dst << " origin " << rrepHeader.GetOrigin ());return;}Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag ttl;ttl.SetTtl (tag.GetTtl() - 1);packet->AddPacketTag (ttl);packet->AddHeader (rrepHeader);TypeHeader tHeader (AODVTYPE_RREP);packet->AddHeader (tHeader);Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ());NS_ASSERT (socket);socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));m_txTrace (packet); // trace
}
  • 设置RecvReplyAck()函数
    接收到RRRP_ACK后进行的操作
void
RoutingProtocol::RecvReplyAck (Ipv4Address neighbor)
{NS_LOG_FUNCTION (this);RoutingTableEntry rt;if(m_routingTable.LookupRoute (neighbor, rt)){rt.m_ackTimer.Cancel ();rt.SetFlag (VALID);m_routingTable.Update (rt);}
}
  • 设置ProcessHello()函数
    当接收到一个hello消息后进行的操作
void
RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiver )
{NS_LOG_FUNCTION (this << "from " << rrepHeader.GetDst ());/**  Whenever a node receives a Hello message from a neighbor, the node* SHOULD make sure that it has an active route to the neighbor, and* create one if necessary.*/RoutingTableEntry toNeighbor;if (!m_routingTable.LookupRoute (rrepHeader.GetDst (), toNeighbor)){Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ rrepHeader.GetDst (), /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (),/*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/ 1, /*nextHop=*/ rrepHeader.GetDst (), /*lifeTime=*/ rrepHeader.GetLifeTime (),/*etx*/ m_nbEtx.GetEtxForNeighbor (rrepHeader.GetDst ())); // etx from hello is useless but node has local etx for neighborm_routingTable.AddRoute (newEntry);}else{toNeighbor.SetLifeTime (std::max (Time (m_allowedHelloLoss * m_helloInterval), toNeighbor.GetLifeTime ()));toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ());toNeighbor.SetValidSeqNo (true);toNeighbor.SetFlag (VALID);toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));toNeighbor.SetHop (1);toNeighbor.SetNextHop (rrepHeader.GetDst ());toNeighbor.SetEtx (m_nbEtx.GetEtxForNeighbor (rrepHeader.GetDst ())); // etx from hello is useless but node has local etx for the neighborm_routingTable.Update (toNeighbor);}if (m_enableHello){m_nb.Update (rrepHeader.GetDst (), Time (m_allowedHelloLoss * m_helloInterval));}
}
  • 设置RecvError()函数
    接收到一个RERR消息后进行的操作
void
RoutingProtocol::RecvError (Ptr<Packet> p, Ipv4Address src )
{NS_LOG_FUNCTION (this << " from " << src);RerrHeader rerrHeader;p->RemoveHeader (rerrHeader);std::map<Ipv4Address, uint32_t> dstWithNextHopSrc;std::map<Ipv4Address, uint32_t> unreachable;m_routingTable.GetListOfDestinationWithNextHop (src, dstWithNextHopSrc);std::pair<Ipv4Address, uint32_t> un;while (rerrHeader.RemoveUnDestination (un)){for (std::map<Ipv4Address, uint32_t>::const_iterator i =dstWithNextHopSrc.begin (); i != dstWithNextHopSrc.end (); ++i){if (i->first == un.first){unreachable.insert (un);}}}std::vector<Ipv4Address> precursors;for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin ();i != unreachable.end ();){if (!rerrHeader.AddUnDestination (i->first, i->second)){TypeHeader typeHeader (AODVTYPE_RERR);Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag tag;tag.SetTtl (1);packet->AddPacketTag (tag);packet->AddHeader (rerrHeader);packet->AddHeader (typeHeader);SendRerrMessage (packet, precursors);rerrHeader.Clear ();}else{RoutingTableEntry toDst;m_routingTable.LookupRoute (i->first, toDst);toDst.GetPrecursors (precursors);++i;}}if (rerrHeader.GetDestCount () != 0){TypeHeader typeHeader (AODVTYPE_RERR);Ptr<Packet> packet = Create<Packet> ();SocketIpTtlTag tag;tag.SetTtl (1);packet->AddPacketTag (tag);packet->AddHeader (rerrHeader);packet->AddHeader (typeHeader);SendRerrMessage (packet, precursors);}m_routingTable.InvalidateRoutesWithDst (unreachable);
}
  • 设置RouteRequestTimerExpire函数
    在路由发现过程中的操作
void
RoutingProtocol::RouteRequestTimerExpire (Ipv4Address dst)
{NS_LOG_LOGIC (this);NS_LOG_DEBUG ("RouteRequestTimerExpire");RoutingTableEntry toDst;if (m_routingTable.LookupValidRoute (dst, toDst)){SendPacketFromQueue (dst, toDst.GetRoute ());NS_LOG_LOGIC ("route to " << dst << " found");NS_LOG_DEBUG ("Route found: " << toDst.GetRoute ()->GetSource () << " --> " << toDst.GetRoute ()->GetGateway () << " --> " << dst);return;}/**  If a route discovery has been attempted RreqRetries times at the maximum TTL without*  receiving any RREP, all data packets destined for the corresponding destination SHOULD be*  dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application.*/if (toDst.GetRreqCnt () == m_rreqRetries){NS_LOG_LOGIC ("route discovery to " << dst << " has been attempted RreqRetries (" << m_rreqRetries << ") times with ttl " << m_netDiameter);m_addressReqTimer.erase (dst);m_routingTable.DeleteRoute (dst);NS_LOG_DEBUG ("Route not found. Drop all packets with dst " << dst);NS_LOG_DEBUG ("Route not found. Drop all packets with dst " << dst);m_queue.DropPacketWithDst (dst);return;}if (toDst.GetFlag () == IN_SEARCH){NS_LOG_LOGIC ("Resend RREQ to " << dst << " previous ttl " << toDst.GetHop ());NS_LOG_DEBUG ("Resend RREQ to " << dst << " previous ttl " << toDst.GetHop ());SendRequest (dst);}else{NS_LOG_DEBUG ("Route down. Stop search. Drop packet with destination " << dst);NS_LOG_DEBUG ("Route down. Stop search. Drop packet with destination " << dst);m_addressReqTimer.erase (dst);m_routingTable.DeleteRoute (dst);m_queue.DropPacketWithDst (dst);//TODO: ? delete ETX metrix ?}
}

NS3中路由协议分析【AODV代码分析】相关推荐

  1. python3颜色代码_python3中布局背景颜色代码分析

    我们想要给某个模块着重突出,以便引起大家注意的时候,通常给那个模块的背景颜色换亮一点.这种情况的操作多见于我们想要突出表格中的某个数据,或是某一项的名称. 在python3中设置布局背景颜色需要通过代 ...

  2. python背景颜色代码大全_python3中布局背景颜色代码分析

    我们想要给某个模块着重突出,以便引起大家注意的时候,通常给那个模块的背景颜色换亮一点.这种情况的操作多见于我们想要突出表格中的某个数据,或是某一项的名称. 在python3中设置布局背景颜色需要通过代 ...

  3. vins中imu融合_VINS-Mono代码分析与总结(最终版)

    VINS-Mono代码分析总结 参考文献 前言 ??视觉与IMU融合的分类: 松耦合和紧耦合:按照是否把图像的Feature加入到状态向量区分,换句话说就是松耦合是在视觉和IMU各自求出的位姿的基础上 ...

  4. 【Android 性能优化】应用启动优化 ( Trace 文件分析 | 结合代码分析 Trace 文件 )

    文章目录 一. Trace 文件查看 二. 结合代码分析 Trace 文件 一. Trace 文件查看 上一篇博客 [Android 性能优化]应用启动优化 ( 方法追踪代码模板 | 示例项目 | S ...

  5. Gooogle Test中的TEST()宏代码分析

    从Primer文档中了解到,一般情况下,在TEST()宏定义一个自己的测试案例,第一部分为单元测试名字,第二部分为测试名.那么TEST()宏的原定义是一个什么样的形式的呢?为什么只需要定义TEST() ...

  6. uboot中关于LCD的代码分析

    以下内容源于朱有鹏<物联网大讲坛>课程的学习,如有侵权,请告知删除. 1.在uboot-jiuding/board.c中,init_sequence中的display_banner中的op ...

  7. php代码分析,THINKPHP代码分析核心.pdf

    前言 TP 的手册相当多,其实不必再出这样的贴子,论技术,我也是菜鸟一个,同时也在学 习当中.看到论坛上多了不少新朋友,不少在抱怨手册看不懂,那我就姑且抛砖引玉,尝试 与新朋友们更简单地.手把手地进入 ...

  8. CC2431 代码分析③-忍辱负重的CC2430

    这节主要分析CC2430的代码,是参考节点的代码,协调器代码我们放到最后分析. 代码分析的原则是事件为导向,我们从CC2431 盲节点code的分析中发现CC2431 向CC2430参考节点发送的信息 ...

  9. delphi 实现屏幕旋转代码_X86指令混淆之函数分析和代码块粉碎

    本文为看雪论坛优秀文章看雪论坛作者ID:三猫原理二进制分析的时候经常遇到经过混淆的函数,所以一直想自己学习实现一个简单的指令乱序demo,也不需要太复杂(其实就是自己菜而已).能阻止IDA F5党(就 ...

最新文章

  1. webpack打开项目命令_webpack前端模块打包工具基本使用的详细记录(一)
  2. 关于log4net日志写入mysql数据库记录
  3. 有SELinux引起的Apache基于端口的虚拟主机启动失败
  4. ASP.NET 2.0的页面缓存功能介绍
  5. 关于量子计算机论文,终于,科学家们找到了只有量子计算机才能解决的问题
  6. SAP ABAP实用技巧介绍系列之锁住某个特定的工作进程
  7. 使用 outlet 在SAP Spartacus 的页面添加自定义 HTML 元素的一个例子
  8. 牛客16589 机器翻译
  9. Java讲课笔记11:构造方法与this关键字
  10. 常见30种数学建模模型_11.12|认识数学模型与数学建模许可
  11. 空间留言工具_新房,拖把等清洁工具都放哪?
  12. 徐州一姑娘写的(女孩看了是自省,男孩看了是激励)
  13. 推荐一款高颜值免费在线SCI绘图工具~~~
  14. 光猫是什么?光纤猫的工作原理及应用范围介绍!
  15. 【ProVerif学习笔记】1:基本使用流程
  16. linux下磁盘坏道修复,linux磁盘坏道修复记录
  17. php薄饼,薄饼的做法大全
  18. uva 10158 War
  19. Excel时间做差,统计加班时长
  20. 云计算 原理与实践期末复习

热门文章

  1. error: cannot connect to daemon
  2. sqlmap 使用方法
  3. python学生管理系统设计实验报告_学生成绩管理系统实验报告(新鲜出炉)
  4. 万字长文:盘点2022全球10大数据泄漏事件(红蓝攻防角度)
  5. [导入]剿杀diskman.exe木马病毒
  6. SEO必备:搜索引擎优化技巧
  7. python :jieba库的使用大全
  8. 一文万字带你入门智能路由器OpenWrt系统,并在虚拟中安装配置OpenWrt
  9. win10最简单定时关机命令
  10. linux哪个版本支持tipc,Linux TIPC 2.0 Programmerapos;s Guide文档.doc