diff --git a/src/routing/aodv/aodv-routing-protocol.cc b/src/routing/aodv/aodv-routing-protocol.cc index c8d80a0ff..5dbe28299 100644 --- a/src/routing/aodv/aodv-routing-protocol.cc +++ b/src/routing/aodv/aodv-routing-protocol.cc @@ -116,22 +116,33 @@ RoutingProtocol::LookupNeighbor (Ipv4Address addr, Neighbor & n) PurgeNeighbor (); for (std::vector::const_iterator i = m_nb.begin (); i != m_nb.end (); ++i) if (i->m_neighborAddress == addr) + { + n = *i; return true; + } return false; } +bool +RoutingProtocol::IsNeighbor(Ipv4Address addr) +{ + for (std::vector::const_iterator i = m_nb.begin (); i != m_nb.end (); ++i) + if (i->m_neighborAddress == addr) return true; + return false; +} + void RoutingProtocol::UpdateNeighbor(Ipv4Address addr, Time expire) { NS_LOG_FUNCTION(this); - PurgeNeighbor (); for (std::vector::iterator i = m_nb.begin (); i != m_nb.end (); ++i) if (i->m_neighborAddress == addr) { - i->m_expireTime = expire; + i->m_expireTime = expire + Simulator::Now(); return; } struct Neighbor neighbor = { addr, expire + Simulator::Now () }; m_nb.push_back (neighbor); + PurgeNeighbor (); } void RoutingProtocol::PurgeNeighbor () @@ -154,7 +165,7 @@ RoutingProtocol::RoutingProtocol () : ALLOWED_HELLO_LOSS (2), FREQUENCY (Seconds (0.5)), m_broadcastID (0), m_seqNo (0), btimer (Timer::CANCEL_ON_DESTROY), htimer (Timer::CANCEL_ON_DESTROY), ntimer (Timer::CANCEL_ON_DESTROY), - rtimer (Timer::CANCEL_ON_DESTROY), lrtimer (Timer::CANCEL_ON_DESTROY) + rtimer (Timer::CANCEL_ON_DESTROY), lrtimer (Timer::CANCEL_ON_DESTROY), m_routeRequestTimer (Timer::CANCEL_ON_DESTROY) { NET_TRAVERSAL_TIME = Scalar (2 * NET_DIAMETER) * NODE_TRAVERSAL_TIME; @@ -163,6 +174,7 @@ RoutingProtocol::RoutingProtocol () : MinHelloInterval = Scalar (0.75) * HELLO_INTERVAL; if(ACTIVE_ROUTE_TIMEOUT > HELLO_INTERVAL) DELETE_PERIOD = Scalar(5) * ACTIVE_ROUTE_TIMEOUT; else DELETE_PERIOD = Scalar(5) * HELLO_INTERVAL; + Ptr dev; } TypeId @@ -235,7 +247,10 @@ RoutingProtocol::Start () m_scb = MakeCallback (&RoutingProtocol::Send, this); m_ecb = MakeCallback (&RoutingProtocol::Drop, this); - // btimer.Schedule (); + + btimer.Schedule(); + ntimer.Schedule(); + rtimer.Schedule(); } Ptr @@ -244,8 +259,7 @@ RoutingProtocol::RouteOutput (Ptr p, const Ipv4Header &header, uint32_t NS_LOG_FUNCTION (this << p->GetUid() << header.GetDestination()); Ptr route; Ipv4Address dst = header.GetDestination (); - Ptr dev; - RoutingTableEntry rt (dev); + RoutingTableEntry rt; bool result = m_routingTable.LookupRoute (dst, rt); if (result && (rt.GetFlag () == RTF_UP)) { @@ -254,6 +268,7 @@ RoutingProtocol::RouteOutput (Ptr p, const Ipv4Header &header, uint32_t NS_ASSERT (route != 0); sockerr = Socket::ERROR_NOTERROR; NS_LOG_LOGIC("exist route to " << route->GetDestination() << " from iface " << route->GetSource()); + UpdateRouteLifeTime(dst, ACTIVE_ROUTE_TIMEOUT); return route; } else @@ -261,7 +276,7 @@ RoutingProtocol::RouteOutput (Ptr p, const Ipv4Header &header, uint32_t QueueEntry newEntry (p, header, m_scb, m_ecb); m_queue.Enqueue (newEntry); sockerr = Socket::ERROR_NOROUTETOHOST; - SendRequest (dst, false, false); + if(rt.GetFlag() != RTF_IN_SEARCH) SendRequest (dst, false, false); return route; } @@ -328,13 +343,17 @@ RoutingProtocol::RouteInput (Ptr p, const Ipv4Header &header, Ptr< { Ptr route = rt.GetRoute (); NS_LOG_LOGIC(route->GetSource()<<" forwarding to " << dst); + UpdateRouteLifeTime(src, ACTIVE_ROUTE_TIMEOUT); UpdateRouteLifeTime(route->GetGateway(), ACTIVE_ROUTE_TIMEOUT); - UpdateNeighbor(route->GetGateway(), ACTIVE_ROUTE_TIMEOUT); + + UpdateNeighbor(route->GetGateway(), ACTIVE_ROUTE_TIMEOUT); //? UpdateNeighbor(src, ACTIVE_ROUTE_TIMEOUT); ucb (route, p, header); return true; } + + QueueEntry newEntry (p, header, ucb, ecb, RTQ_TIMEOUT); m_queue.Enqueue (newEntry); NS_LOG_LOGIC("route not found to "<< dst); @@ -352,9 +371,11 @@ RoutingProtocol::SetIpv4 (Ptr ipv4) rtimer.SetFunction (&RoutingProtocol::RouteCacheTimerExpire, this); lrtimer.SetFunction (&RoutingProtocol::LocalRepairTimerExpire, this); htimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this); + m_routeRequestTimer.SetFunction(&RoutingProtocol::RouteRequestTimerExpire, this); htimer.SetDelay (HELLO_INTERVAL); btimer.SetDelay (BCAST_ID_SAVE); + rtimer.SetDelay (FREQUENCY); m_ipv4 = ipv4; Simulator::ScheduleNow (&RoutingProtocol::Start, this); @@ -427,7 +448,10 @@ RoutingProtocol::SendRequest (Ipv4Address dst, bool G, bool D) { // if we already send maximum number of RREQ if (rt.GetRreqCnt () == RREQ_RETRIES) + { + NS_LOG_LOGIC ("Route does not found to " << dst); return; + } rreqHeader.SetHopCount (rt.GetLastValidHopCount ()); rreqHeader.SetDstSeqno (rt.GetSeqNo ()); @@ -466,6 +490,9 @@ RoutingProtocol::SendRequest (Ipv4Address dst, bool G, bool D) packet->AddHeader (tHeader); socket->Send (packet); } + m_routeRequestTimer.SetArguments(dst); + m_routeRequestTimer.Cancel(); + m_routeRequestTimer.Schedule(NET_TRAVERSAL_TIME); htimer.Cancel(); htimer.Schedule (HELLO_INTERVAL); } @@ -511,7 +538,7 @@ RoutingProtocol::RecvAodv (Ptr socket) } case AODVTYPE_RERR: { - RecvError (packet); + RecvError (packet, senderIfaceAddr); break; } case AODVTYPE_RREP_ACK: @@ -857,14 +884,70 @@ RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiv // TODO process RERR with 'N' flag void -RoutingProtocol::RecvError (Ptr p) +RoutingProtocol::RecvError (Ptr p, Ipv4Address src) { RerrHeader rerrHeader; p->RemoveHeader(rerrHeader); - for(uint8_t i = 0; i < rerrHeader.GetDestCount(); ++i) + std::map dstWithNextHopSrc; + std::map unreachable; + m_routingTable.GetListOfDestinationWithNextHop(src, dstWithNextHopSrc); + std::pair un; + while (rerrHeader.RemoveUnDestination(un)) { - // TODO + if (IsNeighbor (un.first)) SendRerrWhenBreaksLinkToNextHop (un.first); + else + { + for (std::map::const_iterator i = dstWithNextHopSrc.begin(); i != dstWithNextHopSrc.end(); ++i) + if (i->first == un.first) unreachable.insert(un); + } } + + std::vector precursors; + for (std::map::const_iterator i = unreachable.begin (); i != unreachable.end ();) + { + if (!rerrHeader.AddUnDestination (i->first, i->second)) + { + TypeHeader typeHeader (AODVTYPE_RERR); + Ptr packet = Create (); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); + rerrHeader.Clear(); + } + else + { + Ptr dev; + RoutingTableEntry toDst (dev); + m_routingTable.LookupRoute (i->first, toDst); + toDst.GetPrecursors(precursors); + ++i; + } + } + m_routingTable.InvalidateRoutesWithDst(unreachable, DELETE_PERIOD); +} + +void +RoutingProtocol::RouteRequestTimerExpire(Ipv4Address dst) +{ + NS_LOG_LOGIC(this); + RoutingTableEntry toDst; + m_routingTable.LookupRoute(dst, toDst); + if(toDst.GetFlag() == RTF_UP) + { + NS_LOG_LOGIC("route to " << dst << " found"); + return; + } + /** + * If a route discovery has been attempted RREQ_RETRIES 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() == RREQ_RETRIES) + { + NS_LOG_LOGIC("route discovery to " << dst << " has been attempted RREQ_RETRIES times"); + } + NS_LOG_LOGIC("Send new RREQ to " << dst); + SendRequest (dst, false, false); } void @@ -898,7 +981,7 @@ RoutingProtocol::NeighborTimerExpire () void RoutingProtocol::RouteCacheTimerExpire () { - // rt_purge(); + RtPurge(); rtimer.Schedule (FREQUENCY); } @@ -997,31 +1080,36 @@ RoutingProtocol::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop) { RerrHeader rerrHeader; std::vector precursors; - std::map unreachable; + std::map unreachable; Ptr dev; RoutingTableEntry toNextHop (dev); if (!m_routingTable.LookupRoute (nextHop, toNextHop)) return; + toNextHop.GetPrecursors(precursors); rerrHeader.AddUnDestination (nextHop, toNextHop.GetSeqNo ()); - toNextHop.GetPrecursors (precursors); - toNextHop.SetFlag (RTF_DOWN); - toNextHop.SetLifeTime(DELETE_PERIOD); - m_routingTable.Update (nextHop, toNextHop); - - m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable, DELETE_PERIOD); - for (std::map::const_iterator i = unreachable.begin (); i != unreachable.end (); ++i) + m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable); + for (std::map::const_iterator i = unreachable.begin (); i != unreachable.end ();) { - if (!rerrHeader.AddUnDestination (i->first, i->second.GetSeqNo ())) + if (!rerrHeader.AddUnDestination (i->first, i->second)) { TypeHeader typeHeader (AODVTYPE_RERR); Ptr packet = Create (); packet->AddHeader (rerrHeader); packet->AddHeader (typeHeader); SendRerrMessage (packet, precursors); + rerrHeader.Clear(); + } + else + { + RoutingTableEntry toDst (dev); + m_routingTable.LookupRoute (i->first, toDst); + toDst.GetPrecursors(precursors); + ++i; } - } + unreachable.insert(std::make_pair(nextHop, toNextHop.GetSeqNo ())); + m_routingTable.InvalidateRoutesWithDst(unreachable, DELETE_PERIOD); } void @@ -1037,33 +1125,33 @@ RoutingProtocol::SendRerrMessage (Ptr packet, std::vector p m_routingTable.LookupRoute (precursors.front (), toPrecursor); Ptr socket = FindSocketWithInterfaceAddress (toPrecursor.GetInterface ()); socket->SendTo (packet, 0, InetSocketAddress (toPrecursor.GetDestination (), AODV_PORT)); + return; } - else - { - // Should only transmit RERR on those interfaces which have precursor nodes for the broken route - std::vector ifaces; - Ptr dev; - RoutingTableEntry toPrecursor (dev); - for (std::vector::const_iterator i = precursors.begin (); i != precursors.end (); ++i) - { - m_routingTable.LookupRoute (*i, toPrecursor); - bool result = true; - for (std::vector::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i) - if (*i == toPrecursor.GetInterface ()) - { - result = false; - break; - } - if (result) - ifaces.push_back (toPrecursor.GetInterface ()); - } - for (std::vector::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i) - { - Ptr socket = FindSocketWithInterfaceAddress (*i); - socket->Send (packet); - } + // Should only transmit RERR on those interfaces which have precursor nodes for the broken route + std::vector ifaces; + Ptr dev; + RoutingTableEntry toPrecursor (dev); + for (std::vector::const_iterator i = precursors.begin (); i != precursors.end (); ++i) + { + if (!m_routingTable.LookupRoute (*i, toPrecursor)) break; + bool result = true; + for (std::vector::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i) + if (*i == toPrecursor.GetInterface ()) + { + result = false; + break; + } + if (result) + ifaces.push_back (toPrecursor.GetInterface ()); } + + for (std::vector::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i) + { + Ptr socket = FindSocketWithInterfaceAddress (*i); + socket->Send (packet); + } + } Ptr @@ -1091,7 +1179,6 @@ void RoutingProtocol::HandleLinkFailure (Ipv4Address addr) { NS_LOG_FUNCTION(this << addr); - RtPurge(); SendRerrWhenBreaksLinkToNextHop(addr); // TODO } @@ -1100,7 +1187,8 @@ RoutingProtocol::HandleLinkFailure (Ipv4Address addr) void RoutingProtocol::RtPurge () { - m_routingTable.Purge(); + NS_LOG_FUNCTION(this); + m_routingTable.Purge(DELETE_PERIOD); // TODO AODV::rt_purge() } //----------------------------------------------------------------------------- diff --git a/src/routing/aodv/aodv-routing-protocol.h b/src/routing/aodv/aodv-routing-protocol.h index 6847baebc..df2c067ba 100644 --- a/src/routing/aodv/aodv-routing-protocol.h +++ b/src/routing/aodv/aodv-routing-protocol.h @@ -156,7 +156,8 @@ private: } }; bool LookupNeighbor (Ipv4Address addr, Neighbor & n); - void UpdateNeighbor(Ipv4Address addr, Time expire); + bool IsNeighbor (Ipv4Address addr); + void UpdateNeighbor (Ipv4Address addr, Time expire); void PurgeNeighbor (); std::vector m_nb; //\} @@ -168,6 +169,8 @@ private: /// Routing table RoutingTable m_routingTable; + /// Routing entry for desired destination + std::vector m_desired; /// A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route. AodvQueue m_queue; /// Broadcast ID @@ -212,8 +215,8 @@ private: void RecvRequest (Ptr p, Ipv4Address receiver, Ipv4Address src, Ptr socket); /// Receive RREP void RecvReply (Ptr p, Ipv4Address my ,Ipv4Address src); - /// Receive RERR - void RecvError (Ptr p); + /// Receive RERR from node with address src + void RecvError (Ptr p, Ipv4Address src); //\} ///\name Send @@ -253,6 +256,8 @@ private: void RouteCacheTimerExpire (); Timer lrtimer; void LocalRepairTimerExpire (); + Timer m_routeRequestTimer; + void RouteRequestTimerExpire(Ipv4Address dst); //\} }; diff --git a/src/routing/aodv/aodv-rqueue.cc b/src/routing/aodv/aodv-rqueue.cc index c9fa2331d..ed72b6076 100644 --- a/src/routing/aodv/aodv-rqueue.cc +++ b/src/routing/aodv/aodv-rqueue.cc @@ -47,7 +47,6 @@ AodvQueue::GetSize () void AodvQueue::Enqueue(QueueEntry & entry) { - // Purge any packets that have timed out. Purge(); entry.m_expire = Simulator::Now() + m_timeout; diff --git a/src/routing/aodv/aodv-rtable.cc b/src/routing/aodv/aodv-rtable.cc index 9b197d9da..21ce429aa 100644 --- a/src/routing/aodv/aodv-rtable.cc +++ b/src/routing/aodv/aodv-rtable.cc @@ -48,11 +48,6 @@ RoutingTableEntry::RoutingTableEntry(Ptr dev, Ipv4Address dst, bool v m_ipv4Route->SetSource(iface); m_ipv4Route->SetOutputDevice(dev); m_flag = RTF_UP; - for(uint8_t i = 0; i < MAX_HISTORY; ++i) - { - rt_disc_latency[i] = 0; - } - hist_indx = 0; } RoutingTableEntry::~RoutingTableEntry() @@ -115,14 +110,14 @@ RoutingTableEntry::GetPrecursors(std::vector & prec) const } void -RoutingTableEntry::Down (Time badLinkLifetime) +RoutingTableEntry::Invalidate (Time badLinkLifetime) { if(m_flag == RTF_DOWN) return; m_lastHopCount = m_hops; m_hops = INFINITY2; m_flag = RTF_DOWN; - m_lifeTime = badLinkLifetime; + m_lifeTime = badLinkLifetime + Simulator::Now(); } void @@ -161,7 +156,7 @@ RoutingTableEntry::Print(std::ostream & os) const */ bool -RoutingTable::LookupRoute(Ipv4Address id, RoutingTableEntry & rt) const +RoutingTable::LookupRoute(Ipv4Address id, RoutingTableEntry & rt) { std::map::const_iterator i = m_ipv4AddressEntry.find(id); if (i == m_ipv4AddressEntry.end()) return false; @@ -204,28 +199,38 @@ RoutingTable::SetEntryState (Ipv4Address id, uint8_t state) } void -RoutingTable::GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map unreachable, Time badLinkLifetime) +RoutingTable::GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map unreachable) { unreachable.clear(); - for(std::map::iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end(); ++i) - { + for(std::map::const_iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end(); ++i) if ( (i->second.GetNextHop() == nextHop) && (i->second.GetFlag() == RTF_UP) && (!i->second.IsPrecursorListEmpty()) ) - { - unreachable.insert(std::make_pair(i->first, i->second)); - if(i->second.GetValidSeqNo()) - i->second.SetSeqNo(i->second.GetSeqNo()); - i->second.SetFlag(RTF_DOWN); - i->second.SetLifeTime(Simulator::Now() + badLinkLifetime); - } - } + unreachable.insert(std::make_pair(i->first, i->second.GetSeqNo())); } void -RoutingTable::Purge() +RoutingTable::InvalidateRoutesWithDst(const std::map & unreachable, Time badLinkLifetime) +{ + Purge (badLinkLifetime); + for(std::map::iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end(); ++i) + { + for(std::map::const_iterator j = unreachable.begin(); j != unreachable.end(); ++j) + if ( (i->first == j->first) && (i->second.GetFlag() == RTF_UP)) + i->second.Invalidate(badLinkLifetime); + } + +} + +void +RoutingTable::Purge(Time badLinkLifetime) { for(std::map::iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end();) { - if(i->second.GetLifeTime() < Simulator::Now()) m_ipv4AddressEntry.erase(i++); + if(i->second.GetLifeTime() < Simulator::Now()) + { + if(i->second.GetFlag() == RTF_DOWN) + m_ipv4AddressEntry.erase(i++); + else if (i->second.GetFlag() == RTF_UP) i->second.Invalidate(badLinkLifetime); + } else ++i; } } diff --git a/src/routing/aodv/aodv-rtable.h b/src/routing/aodv/aodv-rtable.h index a30aa132e..37ef652c8 100644 --- a/src/routing/aodv/aodv-rtable.h +++ b/src/routing/aodv/aodv-rtable.h @@ -35,6 +35,7 @@ #include "ns3/ipv4-route.h" #include "ns3/ipv4-address.h" #include "ns3/nstime.h" +#include "ns3/timer.h" #include "ns3/net-device.h" @@ -59,7 +60,7 @@ enum RouteFlags class RoutingTableEntry { public: - RoutingTableEntry(Ptr dev,Ipv4Address dst = Ipv4Address(), bool vSeqNo = false, u_int32_t m_seqNo = 0, Ipv4Address iface = Ipv4Address(), u_int16_t hops = 0, + RoutingTableEntry(Ptr dev = 0,Ipv4Address dst = Ipv4Address(), bool vSeqNo = false, u_int32_t m_seqNo = 0, Ipv4Address iface = Ipv4Address(), u_int16_t hops = 0, Ipv4Address nextHop = Ipv4Address(), Time lifetime = Seconds(0)); ~RoutingTableEntry(); @@ -98,7 +99,7 @@ public: /// Mark entry as "down" (i.e. disable it) - void Down (Time badLinkLifetime); + void Invalidate (Time badLinkLifetime); ///\name Fields //\{ Ipv4Address GetDestination() const { return m_ipv4Route->GetDestination(); } @@ -122,8 +123,6 @@ public: void SetRreqCnt(uint8_t n) { m_reqCount = n; } uint8_t GetRreqCnt() const { return m_reqCount; } void IncrementRreqCnt() { m_reqCount++; } - void SetRreqTimeout(Time t) {m_reqTimeout = t; } - Time GetRreqTimeout() const { return m_reqTimeout; } /// Return last valid hop count uint16_t GetLastValidHopCount() { return m_lastHopCount; } //\} @@ -137,6 +136,7 @@ public: return (m_ipv4Route->GetDestination() == dst); } void Print(std::ostream & os) const; + private: /// Valid Destination Sequence Number flag bool m_validSeqNo; @@ -166,14 +166,9 @@ private: /// List of precursors std::vector m_precursorList; /// When I can send another request - Time m_reqTimeout; + Time m_routeRequestTimout; /// Number of route requests uint8_t m_reqCount; - - // TODO review and delete -#define MAX_HISTORY 3 - double rt_disc_latency[MAX_HISTORY]; - char hist_indx; }; /** @@ -203,22 +198,25 @@ public: * \param rt entry with destination address dst, if exists * \return true on success */ - bool LookupRoute(Ipv4Address dst, RoutingTableEntry & rt) const; + bool LookupRoute(Ipv4Address dst, RoutingTableEntry & rt); /// Update routing table bool Update(Ipv4Address dst, RoutingTableEntry & rt); /// Set routing table entry flags void SetEntryState (Ipv4Address dst, uint8_t state /*TODO use enum*/); /** * Lookup valid routing entries with next hop Address dst and not empty list of precursors. - * Update found routing entries as follows: + */ + void GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map unreachable); + /** + * Update routing entries with this destinations as follows: * 1. The destination sequence number of this routing entry, if it * exists and is valid, is incremented. * 2. The entry is invalidated by marking the route entry as invalid * 3. The Lifetime field is updated to current time plus DELETE_PERIOD. */ - void GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map unreachable, Time badLinkLifetime); - /// Delete all outdated entries - void Purge(); + void InvalidateRoutesWithDst(std::map const & unreachable, Time badLinkLifetime); + /// Delete all outdated entries and invalidate valid entry if Lifetime is expired + void Purge(Time badLinkLifetime); /// Print routing table void Print(std::ostream &os) const;