AODV bugs 772 and 777 fixed
This commit is contained in:
@@ -119,7 +119,7 @@ V4Ping::Receive (Ptr<Socket> socket)
|
||||
Icmpv4Echo echo;
|
||||
p->RemoveHeader (echo);
|
||||
std::map<uint16_t, Time>::iterator i = m_sent.find(echo.GetSequenceNumber());
|
||||
|
||||
|
||||
if (i != m_sent.end () && echo.GetIdentifier () == 0)
|
||||
{
|
||||
uint32_t buf[m_size / 4];
|
||||
@@ -132,7 +132,7 @@ V4Ping::Receive (Ptr<Socket> socket)
|
||||
buf[1] == GetApplicationId ())
|
||||
{
|
||||
Time sendTime = i->second;
|
||||
NS_ASSERT (Simulator::Now () > sendTime);
|
||||
NS_ASSERT (Simulator::Now () >= sendTime);
|
||||
Time delta = Simulator::Now () - sendTime;
|
||||
|
||||
m_sent.erase (i);
|
||||
@@ -166,6 +166,7 @@ V4Ping::Write32 (uint8_t *buffer, uint32_t data)
|
||||
void
|
||||
V4Ping::Send ()
|
||||
{
|
||||
NS_LOG_FUNCTION (m_seq);
|
||||
Ptr<Packet> p = Create<Packet> ();
|
||||
Icmpv4Echo echo;
|
||||
echo.SetSequenceNumber (m_seq);
|
||||
@@ -195,8 +196,8 @@ V4Ping::Send ()
|
||||
header.SetType (Icmpv4Header::ECHO);
|
||||
header.SetCode (0);
|
||||
p->AddHeader (header);
|
||||
m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now()));
|
||||
m_socket->Send (p, 0);
|
||||
m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now()));
|
||||
m_next = Simulator::Schedule (m_interval, & V4Ping::Send, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "ns3/wifi-net-device.h"
|
||||
#include "ns3/adhoc-wifi-mac.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("AodvRoutingProtocol");
|
||||
|
||||
@@ -47,6 +48,48 @@ NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
|
||||
/// UDP Port for AODV control traffic
|
||||
const uint32_t RoutingProtocol::AODV_PORT = 654;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// Tag used by AODV implementation
|
||||
struct DeferredRouteOutputTag : public Tag
|
||||
{
|
||||
/// Positive if output device is fixed in RouteOutput
|
||||
int32_t oif;
|
||||
|
||||
DeferredRouteOutputTag (int32_t o = -1) : Tag(), oif (o) {}
|
||||
|
||||
static TypeId GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::DeferredRouteOutputTag").SetParent<Tag> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId GetInstanceTypeId () const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t GetSerializedSize () const
|
||||
{
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
void Serialize (TagBuffer i) const
|
||||
{
|
||||
i.WriteU32 (oif);
|
||||
}
|
||||
|
||||
void Deserialize (TagBuffer i)
|
||||
{
|
||||
oif = i.ReadU32 ();
|
||||
}
|
||||
|
||||
void Print (std::ostream &os) const
|
||||
{
|
||||
os << "DeferredRouteOutputTag: output interface = " << oif;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
RoutingProtocol::RoutingProtocol () :
|
||||
RreqRetries (2),
|
||||
RreqRateLimit (10),
|
||||
@@ -202,9 +245,6 @@ RoutingProtocol::DoDispose ()
|
||||
void
|
||||
RoutingProtocol::Start ()
|
||||
{
|
||||
m_scb = MakeCallback (&RoutingProtocol::Send, this);
|
||||
m_ecb = MakeCallback (&RoutingProtocol::Drop, this);
|
||||
|
||||
if (EnableHello)
|
||||
{
|
||||
m_nb.ScheduleTimer ();
|
||||
@@ -219,6 +259,10 @@ RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header,
|
||||
Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << header.GetDestination ());
|
||||
if (! p)
|
||||
{
|
||||
return LoopbackRoute (header); // later
|
||||
}
|
||||
if (m_socketAddresses.empty ())
|
||||
{
|
||||
sockerr = Socket::ERROR_NOROUTETOHOST;
|
||||
@@ -236,43 +280,44 @@ RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header,
|
||||
{
|
||||
route = rt.GetRoute ();
|
||||
NS_ASSERT (route != 0);
|
||||
NS_LOG_LOGIC("exist route to " << route->GetDestination() << " from interface " << route->GetSource());
|
||||
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, ActiveRouteTimeout);
|
||||
UpdateRouteLifeTime (route->GetGateway (), ActiveRouteTimeout);
|
||||
return route;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool result = true;
|
||||
// May be null pointer (e.g. tcp-socket give null pointer)
|
||||
if (p != Ptr<Packet> ())
|
||||
{
|
||||
QueueEntry newEntry (p, header, m_scb, m_ecb);
|
||||
result = m_queue.Enqueue (newEntry);
|
||||
if (result)
|
||||
NS_LOG_LOGIC ("Add packet " << p->GetUid() << " to queue");
|
||||
}
|
||||
|
||||
}
|
||||
if ((rt.GetFlag () == INVALID) && result)
|
||||
{
|
||||
SendRequest (dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// Valid route not found, in this case we return 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)
|
||||
uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1);
|
||||
DeferredRouteOutputTag tag (iif);
|
||||
if (! p->PeekPacketTag (tag))
|
||||
{
|
||||
bool result = true;
|
||||
if (p != Ptr<Packet> ())
|
||||
{
|
||||
QueueEntry newEntry (p, header, m_scb, m_ecb);
|
||||
// Some protocols may ask route several times for a single packet.
|
||||
result = m_queue.Enqueue (newEntry);
|
||||
if (result)
|
||||
NS_LOG_LOGIC ("Add packet " << p->GetUid() << " to queue. Protocol " << (uint16_t) header.GetProtocol ());
|
||||
}
|
||||
if (result)
|
||||
SendRequest (dst);
|
||||
p->AddPacketTag (tag);
|
||||
}
|
||||
return LoopbackRoute (header);
|
||||
}
|
||||
|
||||
void
|
||||
RoutingProtocol::DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header,
|
||||
UnicastForwardCallback ucb, ErrorCallback ecb)
|
||||
{
|
||||
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 ());
|
||||
SendRequest (header.GetDestination ());
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -287,17 +332,30 @@ RoutingProtocol::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate of own packet
|
||||
if (IsMyOwnAddress (origin))
|
||||
return true;
|
||||
|
||||
// Local delivery to AODV interfaces
|
||||
// Broadcast local delivery/forwarding
|
||||
for (std::map<Ptr<Socket> , Ipv4InterfaceAddress>::const_iterator j =
|
||||
m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
|
||||
{
|
||||
@@ -339,23 +397,20 @@ RoutingProtocol::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::map<Ptr<Socket> , Ipv4InterfaceAddress>::const_iterator j =
|
||||
m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
|
||||
|
||||
// Unicast local delivery
|
||||
if (m_ipv4->IsDestinationAddress (dst, iif))
|
||||
{
|
||||
Ipv4InterfaceAddress iface = j->second;
|
||||
if (dst == iface.GetLocal ())
|
||||
UpdateRouteLifeTime (origin, ActiveRouteTimeout);
|
||||
RoutingTableEntry toOrigin;
|
||||
if (m_routingTable.LookupRoute (origin, toOrigin))
|
||||
{
|
||||
UpdateRouteLifeTime (origin, ActiveRouteTimeout);
|
||||
RoutingTableEntry toOrigin;
|
||||
if (m_routingTable.LookupRoute (origin, toOrigin))
|
||||
{
|
||||
UpdateRouteLifeTime (toOrigin.GetNextHop (), ActiveRouteTimeout);
|
||||
m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
|
||||
}
|
||||
NS_LOG_LOGIC ("Unicast local delivery to " << iface.GetLocal ());
|
||||
lcb (p, header, iif);
|
||||
return true;
|
||||
UpdateRouteLifeTime (toOrigin.GetNextHop (), ActiveRouteTimeout);
|
||||
m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
|
||||
}
|
||||
NS_LOG_LOGIC ("Unicast local delivery to " << dst);
|
||||
lcb (p, header, iif);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Forwarding
|
||||
@@ -422,7 +477,7 @@ RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4)
|
||||
{
|
||||
NS_ASSERT (ipv4 != 0);
|
||||
NS_ASSERT (m_ipv4 == 0);
|
||||
|
||||
|
||||
if (EnableHello)
|
||||
{
|
||||
m_htimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this);
|
||||
@@ -430,6 +485,18 @@ RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -445,7 +512,7 @@ RoutingProtocol::NotifyInterfaceUp (uint32_t i)
|
||||
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 ());
|
||||
@@ -607,6 +674,18 @@ RoutingProtocol::IsMyOwnAddress (Ipv4Address src)
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<Ipv4Route>
|
||||
RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr) const
|
||||
{
|
||||
NS_ASSERT (m_lo != 0);
|
||||
Ptr<Ipv4Route> rt = Create<Ipv4Route> ();
|
||||
rt->SetDestination (hdr.GetDestination ());
|
||||
rt->SetSource (hdr.GetSource ());
|
||||
rt->SetGateway (Ipv4Address ("127.0.0.1"));
|
||||
rt->SetOutputDevice (m_lo);
|
||||
return rt;
|
||||
}
|
||||
|
||||
void
|
||||
RoutingProtocol::SendRequest (Ipv4Address dst)
|
||||
{
|
||||
@@ -1317,23 +1396,23 @@ RoutingProtocol::SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route)
|
||||
QueueEntry queueEntry;
|
||||
while (m_queue.Dequeue (dst, queueEntry))
|
||||
{
|
||||
DeferredRouteOutputTag tag;
|
||||
Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ());
|
||||
if (p->RemovePacketTag (tag) &&
|
||||
tag.oif != -1 &&
|
||||
tag.oif != m_ipv4->GetInterfaceForDevice (route->GetOutputDevice ()))
|
||||
{
|
||||
NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
|
||||
return;
|
||||
}
|
||||
UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback ();
|
||||
ucb (route, queueEntry.GetPacket (), queueEntry.GetIpv4Header ());
|
||||
Ipv4Header header = queueEntry.GetIpv4Header ();
|
||||
header.SetSource (route->GetSource ());
|
||||
header.SetTtl (header.GetTtl() + 1); // compensate extra TTL decrement by fake loopback routing
|
||||
ucb (route, p, header);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RoutingProtocol::Send (Ptr<Ipv4Route> route, Ptr<const Packet> packet,
|
||||
const Ipv4Header & header)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet->GetUid() << (uint16_t) header.GetProtocol());
|
||||
Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
|
||||
NS_ASSERT(l3 != 0);
|
||||
Ptr<Packet> p = packet->Copy ();
|
||||
l3->Send (p, route->GetSource (), header.GetDestination (),
|
||||
header.GetProtocol (), route);
|
||||
}
|
||||
|
||||
void
|
||||
RoutingProtocol::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop)
|
||||
{
|
||||
@@ -1475,8 +1554,6 @@ RoutingProtocol::SendRerrMessage (Ptr<Packet> packet, std::vector<Ipv4Address> p
|
||||
NS_LOG_LOGIC ("Broadcast RERR message from interface " << i->GetLocal());
|
||||
socket->Send (packet);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Ptr<Socket>
|
||||
@@ -1494,11 +1571,5 @@ RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr ) con
|
||||
return socket;
|
||||
}
|
||||
|
||||
void
|
||||
RoutingProtocol::Drop(Ptr<const Packet> packet, const Ipv4Header & header, Socket::SocketErrno err)
|
||||
{
|
||||
NS_LOG_DEBUG (this <<" drop own packet " << packet->GetUid() << " to " << header.GetDestination () << " from queue. Error " << err);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,9 @@ private:
|
||||
Ptr<Ipv4> m_ipv4;
|
||||
/// Raw socket per each IP interface, map socket -> iface address (IP + mask)
|
||||
std::map< Ptr<Socket>, Ipv4InterfaceAddress > m_socketAddresses;
|
||||
|
||||
/// Loopback device used to defer RREQ until packet will be fully formed
|
||||
Ptr<NetDevice> m_lo;
|
||||
|
||||
/// Routing table
|
||||
RoutingTable m_routingTable;
|
||||
/// A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route.
|
||||
@@ -146,14 +148,11 @@ private:
|
||||
/// Number of RREQs used for RREQ rate control
|
||||
uint16_t m_rreqCount;
|
||||
|
||||
/// Unicast callback for own packets
|
||||
UnicastForwardCallback m_scb;
|
||||
/// Error callback for own packets
|
||||
ErrorCallback m_ecb;
|
||||
|
||||
private:
|
||||
/// Start protocol operation
|
||||
void Start ();
|
||||
/// Queue packet and send route request
|
||||
void DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb);
|
||||
/// If route exists and valid, forward packet.
|
||||
bool Forwarding (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb);
|
||||
/**
|
||||
@@ -180,6 +179,8 @@ private:
|
||||
Ptr<Socket> FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const;
|
||||
/// Process hello message
|
||||
void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr);
|
||||
/// Create loopback route for given header
|
||||
Ptr<Ipv4Route> LoopbackRoute (const Ipv4Header & header) const;
|
||||
|
||||
///\name Receive control packets
|
||||
//\{
|
||||
@@ -199,8 +200,6 @@ private:
|
||||
//\{
|
||||
/// Forward packet from route request queue
|
||||
void SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route);
|
||||
/// Aux. send helper
|
||||
void Send (Ptr<Ipv4Route>, Ptr<const Packet>, const Ipv4Header &);
|
||||
/// Send hello
|
||||
void SendHello ();
|
||||
/// Send RREQ
|
||||
@@ -228,9 +227,6 @@ private:
|
||||
void SendRerrWhenNoRouteToForward (Ipv4Address dst, uint32_t dstSeqNo, Ipv4Address origin);
|
||||
//\}
|
||||
|
||||
/// Notify that packet is dropped for some reason
|
||||
void Drop(Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno);
|
||||
|
||||
/// Hello timer
|
||||
Timer m_htimer;
|
||||
/// Schedule next send of hello message
|
||||
@@ -245,7 +241,6 @@ private:
|
||||
void RouteRequestTimerExpire (Ipv4Address dst);
|
||||
/// Mark link to neighbor node as unidirectional for blacklistTimeout
|
||||
void AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -19,6 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "aodv-regression.h"
|
||||
#include "bug-772.h"
|
||||
#include "loopback.h"
|
||||
|
||||
#include "ns3/mesh-helper.h"
|
||||
#include "ns3/simulator.h"
|
||||
@@ -58,6 +60,12 @@ public:
|
||||
AddTestCase (new ChainRegressionTest ("aodv-chain-regression-test"));
|
||||
// Bug 606 test case, should crash if bug is not fixed
|
||||
AddTestCase (new ChainRegressionTest ("bug-606-test", Seconds (10), 3, Seconds (1)));
|
||||
// Bug 772 UDP test case
|
||||
AddTestCase (new Bug772ChainTest ("udp-chain-test", "ns3::UdpSocketFactory", Seconds (3), 10));
|
||||
// Bug 772 TCP test case
|
||||
AddTestCase (new Bug772ChainTest ("tcp-chain-test", "ns3::TcpSocketFactory", Seconds (3), 10));
|
||||
// Ping loopback test case
|
||||
AddTestCase (new LoopbackTestCase ());
|
||||
}
|
||||
} g_aodvRegressionTestSuite;
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,6 +13,8 @@ def build(bld):
|
||||
'aodv-routing-protocol.cc',
|
||||
'aodv-test-suite.cc',
|
||||
'test/aodv-regression.cc',
|
||||
'test/bug-772.cc',
|
||||
'test/loopback.cc',
|
||||
]
|
||||
|
||||
headers = bld.new_task_gen('ns3header')
|
||||
|
||||
Reference in New Issue
Block a user