AODV bugs 772 and 777 fixed

This commit is contained in:
Pavel Boyko
2010-03-01 09:59:14 +03:00
parent e6fa49b9d0
commit f700786fbe
13 changed files with 165 additions and 88 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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);
};
}

View File

@@ -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;

View File

@@ -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')