From f700786fbe0fc0aa7a9bd2413c48eb465b424774 Mon Sep 17 00:00:00 2001 From: Pavel Boyko Date: Mon, 1 Mar 2010 09:59:14 +0300 Subject: [PATCH] AODV bugs 772 and 777 fixed --- src/applications/v4ping/v4ping.cc | 7 +- src/routing/aodv/aodv-routing-protocol.cc | 217 ++++++++++++------ src/routing/aodv/aodv-routing-protocol.h | 19 +- .../test/aodv-chain-regression-test-0-0.pcap | Bin 6938 -> 6938 bytes .../test/aodv-chain-regression-test-1-0.pcap | Bin 9076 -> 9076 bytes .../test/aodv-chain-regression-test-2-0.pcap | Bin 7450 -> 7450 bytes .../test/aodv-chain-regression-test-3-0.pcap | Bin 7292 -> 7292 bytes .../test/aodv-chain-regression-test-4-0.pcap | Bin 5050 -> 5050 bytes src/routing/aodv/test/aodv-regression.cc | 8 + src/routing/aodv/test/bug-606-test-0-0.pcap | Bin 5456 -> 5456 bytes src/routing/aodv/test/bug-606-test-1-0.pcap | Bin 6368 -> 6368 bytes src/routing/aodv/test/bug-606-test-2-0.pcap | Bin 4790 -> 4790 bytes src/routing/aodv/wscript | 2 + 13 files changed, 165 insertions(+), 88 deletions(-) diff --git a/src/applications/v4ping/v4ping.cc b/src/applications/v4ping/v4ping.cc index b7f79af95..219301734 100644 --- a/src/applications/v4ping/v4ping.cc +++ b/src/applications/v4ping/v4ping.cc @@ -119,7 +119,7 @@ V4Ping::Receive (Ptr socket) Icmpv4Echo echo; p->RemoveHeader (echo); std::map::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) 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 p = Create (); 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); } diff --git a/src/routing/aodv/aodv-routing-protocol.cc b/src/routing/aodv/aodv-routing-protocol.cc index f86f1b502..44c63bf61 100644 --- a/src/routing/aodv/aodv-routing-protocol.cc +++ b/src/routing/aodv/aodv-routing-protocol.cc @@ -35,6 +35,7 @@ #include "ns3/wifi-net-device.h" #include "ns3/adhoc-wifi-mac.h" #include +#include 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 (); + 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 p, const Ipv4Header &header, Ptr 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 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 (); + } 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 ()) - { - 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 ()) - { - 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 p, const Ipv4Header & header, + UnicastForwardCallback ucb, ErrorCallback ecb) +{ + NS_ASSERT (p != 0 && p != Ptr ()); + + 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 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 , Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) { @@ -339,23 +397,20 @@ RoutingProtocol::RouteInput (Ptr p, const Ipv4Header &header, return true; } } - for (std::map , 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) { 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) } 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::CreateSocket (GetObject (), UdpSocketFactory::GetTypeId ()); @@ -607,6 +674,18 @@ RoutingProtocol::IsMyOwnAddress (Ipv4Address src) return false; } +Ptr +RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr) const +{ + NS_ASSERT (m_lo != 0); + Ptr rt = Create (); + 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 route) QueueEntry queueEntry; while (m_queue.Dequeue (dst, queueEntry)) { + DeferredRouteOutputTag tag; + Ptr p = ConstCast (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 route, Ptr packet, - const Ipv4Header & header) -{ - NS_LOG_FUNCTION (this << packet->GetUid() << (uint16_t) header.GetProtocol()); - Ptr l3 = m_ipv4->GetObject (); - NS_ASSERT(l3 != 0); - Ptr 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, std::vector p NS_LOG_LOGIC ("Broadcast RERR message from interface " << i->GetLocal()); socket->Send (packet); } - - } Ptr @@ -1494,11 +1571,5 @@ RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr ) con return socket; } -void -RoutingProtocol::Drop(Ptr packet, const Ipv4Header & header, Socket::SocketErrno err) -{ - NS_LOG_DEBUG (this <<" drop own packet " << packet->GetUid() << " to " << header.GetDestination () << " from queue. Error " << err); -} - } } diff --git a/src/routing/aodv/aodv-routing-protocol.h b/src/routing/aodv/aodv-routing-protocol.h index b068a0b85..370050352 100644 --- a/src/routing/aodv/aodv-routing-protocol.h +++ b/src/routing/aodv/aodv-routing-protocol.h @@ -128,7 +128,9 @@ private: Ptr m_ipv4; /// Raw socket per each IP interface, map socket -> iface address (IP + mask) std::map< Ptr, Ipv4InterfaceAddress > m_socketAddresses; - + /// Loopback device used to defer RREQ until packet will be fully formed + Ptr 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 p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb); /// If route exists and valid, forward packet. bool Forwarding (Ptr p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb); /** @@ -180,6 +179,8 @@ private: Ptr FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const; /// Process hello message void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr); + /// Create loopback route for given header + Ptr 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 route); - /// Aux. send helper - void Send (Ptr, Ptr, 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 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); - }; } diff --git a/src/routing/aodv/test/aodv-chain-regression-test-0-0.pcap b/src/routing/aodv/test/aodv-chain-regression-test-0-0.pcap index 08055edb775b438cabd1e6df519405da85a42f47..e879d113f9b7affc1ff65f14fc524d2abd152b83 100644 GIT binary patch delta 118 zcmbPbHp^^+FC*h*1qtzusVdBj43i)5iB6u+{Ev}g^E{T9{ER$6DcQ+OMK&?=POjlo zoLnjDH2Jld+~k|0UXyo=D@}G4TgE5^R>LX2iBWj+9`R&G(aj1H(-|4Xz#48!Ix$Ls P6~@;6b2h*DYc1FWbzv+Jpgw{CPn}N diff --git a/src/routing/aodv/test/aodv-chain-regression-test-1-0.pcap b/src/routing/aodv/test/aodv-chain-regression-test-1-0.pcap index 7ecf8d9dd1750c39a09a515693a0247220f5460a..7ab3781a7055904f2235fb312c53346092a47bc3 100644 GIT binary patch delta 122 zcmez3_Qh?2FC*hdzsD>r3=9kolh?8bZ|-2_Wn^TSd_h8V@_u&5$#2;9GBRvl#Xet@ zk!SKf1=-2zvYQxrC)i R0}D)7a$=MKEBdZf3jnyPC|Cdh delta 126 zcmez3_Qh?2?_^mXJ$r*&0m<0@dE%a7X|46 delta 14 Wcmdm`zDs?>XJ$sm&0m<0@dE%a9R=zD diff --git a/src/routing/aodv/test/aodv-regression.cc b/src/routing/aodv/test/aodv-regression.cc index bb8bf356a..6795e07a0 100644 --- a/src/routing/aodv/test/aodv-regression.cc +++ b/src/routing/aodv/test/aodv-regression.cc @@ -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; diff --git a/src/routing/aodv/test/bug-606-test-0-0.pcap b/src/routing/aodv/test/bug-606-test-0-0.pcap index 7d0916ae4b2ecf1fdb74559f58e5a33442c516d0..d0665813408601abe706dae035e122514315f52f 100644 GIT binary patch delta 95 zcmcbhbwO)_FC*hdKWk=2hRF$hqLb${|6^p>JddTBk5ORqJ7L+$_QGC_f|LE&6eq71 ucAC6XL~b&-h}UFAQKiY{B2J8AU^Ul8ycoqnYIs?=7#SHE7}zf`0097AoEb_0 delta 93 zcmcbhbwO)_FC)W7KWk=2#>okMqLb${|6^p_JddTBkCA`!J7L+$_QGD16@^76^Yigd wUM=jzCol1qLZ()+Hc;#!p}IFo1JU(Nmg-T0M~;GrvLx| diff --git a/src/routing/aodv/test/bug-606-test-2-0.pcap b/src/routing/aodv/test/bug-606-test-2-0.pcap index c414ed66633f93f7699b59a457b24f5bb07269b5..25aded0ecac416d7344defa4e0da893d83bd0e20 100644 GIT binary patch delta 14 Wcmdm{x=nS%XJ$r*&0m-g@c{rXb_Lh~ delta 16 Ycmdm{x=nS%XXeTFtX!M_GVkOA06e`0xBvhE diff --git a/src/routing/aodv/wscript b/src/routing/aodv/wscript index 7e3d9f851..ca4c3d2c4 100644 --- a/src/routing/aodv/wscript +++ b/src/routing/aodv/wscript @@ -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')