概述
详尽分析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 = 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)路由到环回,从环回接收并传递到RouteInput
uint32_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 IP
NS_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来发送RREQ
return true;
}
}
// Duplicate of own packet,自身数据包的副本
if (IsMyOwnAddress (origin))
return true;
// AODV is not a multicast routing protocol
if (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)
{ // 单播本地交付到dst
NS_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;
}
// Forwarding
return 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 loopback
NS_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 route
RoutingTableEntry 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 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.GetBroadcast (), AODV_PORT));
socket->SetAllowBroadcast (true);
socket->SetIpRecvTtl (true);
m_socketSubnetBroadcastAddresses.insert (std::make_pair (socket, iface));
// Add local broadcast record to the routing table
Ptr<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 possible
Ptr<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 socket
Ptr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0));
NS_ASSERT (socket);
socket->Close ();
m_socketAddresses.erase (socket);
// Close socket
socket = 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 device
for (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;
}
else
m_rreqCount++;
// Create RREQ header
RreqHeader rreqHeader;
rreqHeader.SetDst (dst);
RoutingTableEntry rt;
// Using the Hop field in Routing Table to manage the expanding ring search
uint16_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 ());
else
rreqHeader.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 == NetDiameter
if (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 aodv
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;
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 otherwise
Ipv4Address 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 backoff
retry = 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 socket
Address sourceAddress;
Ptr<Packet> packet = socket->RecvFrom (sourceAddress);
InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
Ipv4Address sender = inetSourceAddr.GetIpv4 ();
// Get reciver address from socket, this is my IP
Ipv4Address 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 value
UpdateRouteToNeighbor (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 packet
uint8_t lppTimeStamp = lppHeader.GetLppId ();
uint16_t numNeighbors = lppHeader.GetNumberNeighbors ();
std::pair<Ipv4Address, uint8_t> un;
// Search for my IP address in LPP packet header
uint8_t lppReverse = 0; // if there is no my address in the packet header lpp reverse should be 0
for (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 metrix
RoutingTableEntry 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 blacklist
RoutingTableEntry 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 count
uint8_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 node
uint32_t etx = m_nbEtx.GetEtxForNeighbor (src); // src is always neighbor, origin maybe isn't
if (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...");
}
else
NS_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 table
Ptr<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 route
if (toOrigin.GetValidSeqNo ())
{
if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0)
toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); // update sequence number with newer one
}
else
toOrigin.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 route
toNeighbor.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 neighbors
m_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 forwarding
rreqHeader.SetDstSeqno (toDst.GetSeqNo ());
rreqHeader.SetUnknownSeqno (false);
}
}
// Forward RREQ
SocketIpTtlTag 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 otherwise
Ipv4Address 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 message
if (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 node
uint32_t etx = m_nbEtx.GetEtxForNeighbor (sender); // sender is always neighbor, destination maybe isn't
if (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 testing
NS_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 smaller
else 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 back
if (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 precursors
if (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 neighbor
m_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 neighbor
m_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代码分析】的全部内容,希望文章能够帮你解决NS3中路由协议分析【AODV代码分析】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复