From cfb67261a1a4c519ff5025e53596df56afdf3bac Mon Sep 17 00:00:00 2001 From: Borovkova Elena Date: Fri, 14 Aug 2009 18:14:16 +0400 Subject: [PATCH] local repair in progress --- src/routing/aodv/aodv-routing-protocol.cc | 96 ++++++++++++++--------- src/routing/aodv/aodv-routing-protocol.h | 5 +- src/routing/aodv/aodv-rtable.cc | 51 ++++++------ src/routing/aodv/aodv-rtable.h | 9 ++- 4 files changed, 96 insertions(+), 65 deletions(-) diff --git a/src/routing/aodv/aodv-routing-protocol.cc b/src/routing/aodv/aodv-routing-protocol.cc index c5f61ab60..d4559169d 100644 --- a/src/routing/aodv/aodv-routing-protocol.cc +++ b/src/routing/aodv/aodv-routing-protocol.cc @@ -88,6 +88,7 @@ RoutingProtocol::RoutingProtocol () : m_requestId (0), m_seqNo (0), m_nb(HelloInterval), + m_repairedDst (Ipv4Address ()), htimer (Timer::CANCEL_ON_DESTROY), rtimer (Timer::CANCEL_ON_DESTROY), lrtimer (Timer::CANCEL_ON_DESTROY) @@ -95,7 +96,7 @@ RoutingProtocol::RoutingProtocol () : { if (EnableHello) { - m_nb.SetCallback (MakeCallback (&RoutingProtocol::HandleLinkFailure, this)); + m_nb.SetCallback (MakeCallback (&RoutingProtocol::SendRerrWhenBreaksLinkToNextHop, this)); } /* BlackListTimeout should be suitably increased if an expanding ring search is used. In such cases, it should be * {[(TtlThreshold - TtlStart)/TtlIncrement] + 1 + RreqRetries} *NetTraversalTime. @@ -254,7 +255,7 @@ RoutingProtocol::RouteOutput (Ptr p, const Ipv4Header &header, uint32_t RoutingTableEntry rt; if (m_routingTable.LookupRoute (dst, rt)) { - if (rt.GetFlag () == RTF_UP) + if (rt.GetFlag () == VALID) { route = rt.GetRoute (); NS_ASSERT (route != 0); @@ -268,9 +269,9 @@ RoutingProtocol::RouteOutput (Ptr p, const Ipv4Header &header, uint32_t QueueEntry newEntry (p, header, m_scb, m_ecb); m_queue.Enqueue (newEntry); - if (rt.GetFlag () == RTF_DOWN) + if (rt.GetFlag () == INVALID) { - m_routingTable.SetEntryState (dst, RTF_IN_SEARCH); + m_routingTable.SetEntryState (dst, IN_SEARCH); if (EnableExpandingRingSearch) SendRequest (dst, rt.GetHop () + TtlIncrement); else @@ -322,16 +323,10 @@ RoutingProtocol::RouteInput (Ptr p, const Ipv4Header &header, Ptr< m_idCache.InsertId (origin, p->GetUid (), PathDiscoveryTime); UpdateRouteLifeTime (origin, ActiveRouteTimeout); NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ()); + Ptr packet = p->Copy(); lcb (p, header, iif); - Ptr l3 = m_ipv4->GetObject (); - NS_ASSERT(l3 != 0); - // Broadcast packet from all interfaces. - for (std::map , Ipv4InterfaceAddress>::const_iterator i = m_socketAddresses.begin (); i != m_socketAddresses.end (); ++i) - { - Ptr packet = p->Copy (); - Ptr route; - l3->Send (packet, i->second.GetLocal (), i->second.GetBroadcast (), header.GetProtocol (), route); - } + Ptr route; + ucb (route, packet, header); return true; } } @@ -365,7 +360,7 @@ RoutingProtocol::Forwarding (Ptr p, const Ipv4Header & header, Uni RoutingTableEntry toDst; if (m_routingTable.LookupRoute (dst, toDst)) { - if (toDst.GetFlag () == RTF_DOWN && EnableLocalRepair) + if (toDst.GetFlag () == INVALID && EnableLocalRepair && !lrtimer.IsRunning()) { if (toDst.GetHop () > MaxRepairTtl) return false; @@ -375,13 +370,13 @@ RoutingProtocol::Forwarding (Ptr p, const Ipv4Header & header, Uni NS_LOG_LOGIC("Local repair "<< dst); return true; } - else if (toDst.GetFlag () == RTF_IN_REPAIR) + else if (toDst.GetFlag () == BEING_REPAIRED) { QueueEntry newEntry (p, header, ucb, ecb, MaxQueueTime); m_queue.Enqueue (newEntry); return true; } - else if (toDst.GetFlag () == RTF_UP) + else if (toDst.GetFlag () == VALID) { Ptr route = toDst.GetRoute (); NS_LOG_LOGIC(route->GetSource()<<" forwarding to " << dst << " from " << origin << " packet " << p->GetUid ()); @@ -496,7 +491,7 @@ RoutingProtocol::SendRequest (Ipv4Address dst, uint16_t ttl) Ptr dev; rreqHeader.SetUnknownSeqno (true); RoutingTableEntry newEntry (dev, dst, false, 0, Ipv4InterfaceAddress (), 0, Ipv4Address (), Seconds (0)); - newEntry.SetFlag (RTF_IN_SEARCH); + newEntry.SetFlag (IN_SEARCH); m_routingTable.AddRoute (newEntry); } @@ -616,7 +611,7 @@ RoutingProtocol::UpdateRouteLifeTime (Ipv4Address addr, Time lifetime ) RoutingTableEntry rt; if (m_routingTable.LookupRoute (addr, rt)) { - rt.SetFlag (RTF_UP); + rt.SetFlag (VALID); rt.SetRreqCnt (0); rt.SetLifeTime (std::max (lifetime, rt.GetLifeTime ())); m_routingTable.Update (rt); @@ -745,7 +740,7 @@ RoutingProtocol::RecvRequest (Ptr p, Ipv4Address receiver, Ipv4Address s */ if (rreqHeader.GetUnknownSeqno () || ( (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) > 0) && toDst.GetValidSeqNo () )) { - if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag() == RTF_UP) + if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag() == VALID) { m_routingTable.LookupRoute (origin, toOrigin); SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratiousRrep ()); @@ -890,6 +885,18 @@ RoutingProtocol::RecvReply (Ptr p, Ipv4Address receiver, Ipv4Address sen return; } + if (dst == m_repairedDst) + { + RoutingTableEntry toDst; + m_routingTable.LookupRoute (dst, toDst); + if (toDst.GetHop () < rrepHeader.GetHopCount ()) + { + lrtimer.Cancel (); + m_repairedDst = Ipv4Address (); + SendRerr (dst, true); + } + } + /* * If the route table entry to the destination is created or updated, then the following actions occur: * - the route is marked as active, @@ -923,7 +930,7 @@ RoutingProtocol::RecvReply (Ptr p, Ipv4Address receiver, Ipv4Address sen else { // (iii) the sequence numbers are the same, but the route is marked as inactive. - if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (toDst.GetFlag () != RTF_UP)) + if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (toDst.GetFlag () != VALID)) { m_routingTable.Update (newEntry); } @@ -951,7 +958,7 @@ RoutingProtocol::RecvReply (Ptr p, Ipv4Address receiver, Ipv4Address sen NS_LOG_LOGIC ("receiver " << receiver << " origin " << rrepHeader.GetOrigin ()); if (IsMyOwnAddress (rrepHeader.GetOrigin ())) { - if (toDst.GetFlag () == RTF_IN_SEARCH) + if (toDst.GetFlag () == IN_SEARCH) { m_routingTable.Update (newEntry); m_addressReqTimer[dst].Cancel (); @@ -1019,7 +1026,7 @@ RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiv toNeighbor.SetLifeTime (std::max (Scalar (AllowedHelloLoss) * HelloInterval, toNeighbor.GetLifeTime ())); toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ()); toNeighbor.SetValidSeqNo (true); - toNeighbor.SetFlag (RTF_UP); + toNeighbor.SetFlag (VALID); toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver))); toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0)); m_routingTable.Update (toNeighbor); @@ -1030,12 +1037,12 @@ RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiv } } -// TODO process RERR with 'N' flag void RoutingProtocol::RecvError (Ptr p, Ipv4Address src ) { RerrHeader rerrHeader; p->RemoveHeader (rerrHeader); + bool noDelete = rerrHeader.GetNoDelete (); std::map dstWithNextHopSrc; std::map unreachable; m_routingTable.GetListOfDestinationWithNextHop (src, dstWithNextHopSrc); @@ -1072,7 +1079,8 @@ RoutingProtocol::RecvError (Ptr p, Ipv4Address src ) ++i; } } - m_routingTable.InvalidateRoutesWithDst (unreachable); + if (!noDelete) + m_routingTable.InvalidateRoutesWithDst (unreachable); } void @@ -1081,7 +1089,7 @@ RoutingProtocol::RouteRequestTimerExpire (Ipv4Address dst, uint16_t lastTtl ) NS_LOG_LOGIC(this); RoutingTableEntry toDst; m_routingTable.LookupRoute (dst, toDst); - if (toDst.GetFlag () == RTF_UP) + if (toDst.GetFlag () == VALID) { SendPacketFromQueue (dst, toDst.GetRoute ()); NS_LOG_LOGIC ("route to " << dst << " found"); @@ -1102,7 +1110,7 @@ RoutingProtocol::RouteRequestTimerExpire (Ipv4Address dst, uint16_t lastTtl ) return; } - if (toDst.GetFlag () == RTF_IN_SEARCH) + if (toDst.GetFlag () == IN_SEARCH) { if (lastTtl + TtlIncrement > TtlThreshold) @@ -1140,7 +1148,12 @@ RoutingProtocol::HelloTimerExpire () void RoutingProtocol::LocalRepairTimerExpire () { - // TODO start local repair procedure + NS_LOG_LOGIC ("Local repair failed. Drop packet with destination IP address " << m_repairedDst << " and send RERR message"); + m_queue.DropPacketWithDst (m_repairedDst); + SendRerr (m_repairedDst, false); + RoutingTableEntry toDst; + m_routingTable.SetEntryState (m_repairedDst, INVALID); + m_repairedDst = Ipv4Address (); } void @@ -1224,7 +1237,6 @@ RoutingProtocol::Send (Ptr route, Ptr packet, const Ipv void RoutingProtocol::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop ) { - RerrHeader rerrHeader; std::vector precursors; std::map unreachable; @@ -1258,6 +1270,23 @@ RoutingProtocol::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop ) m_routingTable.InvalidateRoutesWithDst (unreachable); } +void +RoutingProtocol::SendRerr (Ipv4Address dst, bool noDelete) +{ + RerrHeader rerrHeader; + std::vector precursors; + RoutingTableEntry toDst; + if (!m_routingTable.LookupRoute (dst, toDst)) + return; + toDst.GetPrecursors (precursors); + rerrHeader.AddUnDestination (dst, toDst.GetSeqNo ()); + TypeHeader typeHeader (AODVTYPE_RERR); + Ptr packet = Create (); + packet->AddHeader (rerrHeader); + packet->AddHeader (typeHeader); + SendRerrMessage (packet, precursors); +} + void RoutingProtocol::SendRerrMessage (Ptr packet, std::vector precursors ) { @@ -1338,17 +1367,12 @@ RoutingProtocol::LocalRouteRepair (Ipv4Address dst, Ipv4Address origin ) if (!m_routingTable.LookupRoute (origin, toOrigin)) return; uint16_t ttl = std::max (toOrigin.GetHop () * 0.5, (double) toDst.GetHop ()) + LocalAddTtl; - ttl++; + SendRequest (dst, ttl); + toDst.SetFlag (BEING_REPAIRED); + lrtimer.Schedule(Scalar(2*(ttl + TimeoutBuffer)) * NodeTraversalTime); } -void -RoutingProtocol::HandleLinkFailure (Ipv4Address addr ) -{ - NS_LOG_FUNCTION(this << addr); - SendRerrWhenBreaksLinkToNextHop (addr); - // TODO -} } } diff --git a/src/routing/aodv/aodv-routing-protocol.h b/src/routing/aodv/aodv-routing-protocol.h index 9045e5cbf..df4876b12 100644 --- a/src/routing/aodv/aodv-routing-protocol.h +++ b/src/routing/aodv/aodv-routing-protocol.h @@ -153,6 +153,8 @@ private: IdCache m_idCache; /// Handle neighbors Neighbors m_nb; + /// Address of the destination, which currently repaired. + Ipv4Address m_repairedDst; /// Unicast callback for own packets UnicastForwardCallback m_scb; @@ -173,8 +175,6 @@ private: * \return true if node forward packet or try to repair route. */ bool Forwarding (Ptr p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb); - /// Process broken link - void HandleLinkFailure (Ipv4Address id); /** * To reduce congestion in a network, repeated attempts by a source node at route discovery * for a single destination MUST utilize a binary exponential backoff. @@ -231,6 +231,7 @@ private: void SendReplyAck (Ipv4Address neighbor); /// Initiate RERR void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop); + void SendRerr (Ipv4Address dst, bool noDelete); /// Forward RERR void SendRerrMessage(Ptr packet, std::vector precursors); /** diff --git a/src/routing/aodv/aodv-rtable.cc b/src/routing/aodv/aodv-rtable.cc index bb93de4fa..6dd85a072 100644 --- a/src/routing/aodv/aodv-rtable.cc +++ b/src/routing/aodv/aodv-rtable.cc @@ -44,7 +44,7 @@ namespace aodv RoutingTableEntry::RoutingTableEntry (Ptr dev, Ipv4Address dst, bool vSeqNo, u_int32_t seqNo, Ipv4InterfaceAddress iface, u_int16_t hops, Ipv4Address nextHop, Time lifetime ) : m_validSeqNo (vSeqNo), m_seqNo (seqNo), m_hops (hops), m_lifeTime (lifetime + Simulator::Now ()), - m_iface (iface), m_flag (RTF_UP), m_reqCount (0), m_blackListState (false), m_blackListTimeout (Simulator::Now ()), + m_iface (iface), m_flag (VALID), m_reqCount (0), m_blackListState (false), m_blackListTimeout (Simulator::Now ()), m_ackTimer (Timer::CANCEL_ON_DESTROY) { m_ipv4Route = Create (); @@ -122,9 +122,9 @@ RoutingTableEntry::GetPrecursors (std::vector & prec ) const void RoutingTableEntry::Invalidate (Time badLinkLifetime ) { - if (m_flag == RTF_DOWN) + if (m_flag == INVALID) return; - m_flag = RTF_DOWN; + m_flag = INVALID; m_reqCount = 0; m_lifeTime = badLinkLifetime + Simulator::Now (); } @@ -135,22 +135,27 @@ RoutingTableEntry::Print (std::ostream & os ) const os << m_ipv4Route->GetDestination () << "\t" << m_ipv4Route->GetGateway () << "\t" << m_iface.GetLocal ()<< "\t"; switch (m_flag) { - case RTF_UP: + case VALID: { os << "UP"; break; } - case RTF_DOWN: + case INVALID: { os << "DOWN"; break; } - case RTF_IN_REPAIR: + case BEING_REPAIRED: { os << "IN_REPAIR"; break; } - case RTF_IN_SEARCH: + case REPAIRABLE: + { + os << "REPAIRABLE"; + break; + } + case IN_SEARCH: { os << "IN_SEARCH"; break; @@ -187,7 +192,7 @@ AodvRtableEntryTest::RunTests () NS_TEST_ASSERT_EQUAL (rt.GetHop(), 5); NS_TEST_ASSERT_EQUAL (rt.GetNextHop (), Ipv4Address ("3.3.3.3")); NS_TEST_ASSERT_EQUAL (rt.GetLifeTime (), Seconds (10)); - NS_TEST_ASSERT_EQUAL (rt.GetFlag (), RTF_UP); + NS_TEST_ASSERT_EQUAL (rt.GetFlag (), VALID); NS_TEST_ASSERT_EQUAL (rt.GetRreqCnt(), 0); NS_TEST_ASSERT_EQUAL (rt.IsPrecursorListEmpty(), true); @@ -199,10 +204,10 @@ AodvRtableEntryTest::RunTests () NS_TEST_ASSERT_EQUAL (rt.GetInterface(), iface2); rt.SetValidSeqNo(false); NS_TEST_ASSERT_EQUAL (rt.GetValidSeqNo (), false); - rt.SetFlag(RTF_DOWN); - NS_TEST_ASSERT_EQUAL (rt.GetFlag (), RTF_DOWN); - rt.SetFlag(RTF_IN_REPAIR); - NS_TEST_ASSERT_EQUAL (rt.GetFlag (), RTF_IN_REPAIR); + rt.SetFlag(INVALID); + NS_TEST_ASSERT_EQUAL (rt.GetFlag (), INVALID); + rt.SetFlag(BEING_REPAIRED); + NS_TEST_ASSERT_EQUAL (rt.GetFlag (), BEING_REPAIRED); rt.SetHop(12); NS_TEST_ASSERT_EQUAL (rt.GetHop (), 12); rt.SetLifeTime(Seconds(1)); @@ -218,7 +223,7 @@ AodvRtableEntryTest::RunTests () rt.IncrementRreqCnt(); NS_TEST_ASSERT_EQUAL (rt.GetRreqCnt(), 3); rt.Invalidate(Seconds(13)); - NS_TEST_ASSERT_EQUAL (rt.GetFlag (), RTF_DOWN); + NS_TEST_ASSERT_EQUAL (rt.GetFlag (), INVALID); NS_TEST_ASSERT_EQUAL (rt.GetLifeTime (), Seconds (13)); rt.SetLifeTime(Seconds(0.1)); NS_TEST_ASSERT_EQUAL (rt.GetLifeTime (), Seconds (0.1)); @@ -283,7 +288,7 @@ RoutingTable::DeleteRoute (Ipv4Address dst ) bool RoutingTable::AddRoute (RoutingTableEntry & rt ) { - if (rt.GetFlag () != RTF_IN_SEARCH) + if (rt.GetFlag () != IN_SEARCH) rt.SetRreqCnt (0); std::pair::iterator, bool> result = m_ipv4AddressEntry.insert (std::make_pair (rt.GetDestination (), rt)); return result.second; @@ -296,7 +301,7 @@ RoutingTable::Update (RoutingTableEntry & rt ) if (i == m_ipv4AddressEntry.end ()) return false; i->second = rt; - if (i->second.GetFlag () != RTF_IN_SEARCH) + if (i->second.GetFlag () != IN_SEARCH) i->second.SetRreqCnt (0); return true; } @@ -318,7 +323,7 @@ RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop, 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 ())) + if ((i->second.GetNextHop () == nextHop) && (i->second.GetFlag () == VALID) && (!i->second.IsPrecursorListEmpty ())) unreachable.insert (std::make_pair (i->first, i->second.GetSeqNo ())); } @@ -329,7 +334,7 @@ RoutingTable::InvalidateRoutesWithDst (const std::map & u 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)) + if ((i->first == j->first) && (i->second.GetFlag () == VALID)) { NS_LOG_LOGIC ("invalidate route with dst " << i->first); i->second.Invalidate (m_badLinkLifetime); @@ -347,13 +352,13 @@ RoutingTable::Purge () { if (i->second.GetLifeTime () < Seconds (0)) { - if (i->second.GetFlag () == RTF_DOWN) + if (i->second.GetFlag () == INVALID) { std::map::iterator tmp = i; ++i; m_ipv4AddressEntry.erase (tmp); } - else if (i->second.GetFlag () == RTF_UP) + else if (i->second.GetFlag () == VALID) { NS_LOG_LOGIC ("invalidate route with dst " << i->first ); i->second.Invalidate (m_badLinkLifetime); @@ -429,13 +434,13 @@ AodvRtableTest::RunTests () RoutingTableEntry rt3; NS_TEST_ASSERT_EQUAL (rtable.LookupRoute(Ipv4Address("10.0.0.1"), rt), false); NS_TEST_ASSERT_EQUAL (rtable.Update (rt3), false); - NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("10.0.0.1"), RTF_DOWN), false); - NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("1.2.3.4"), RTF_IN_SEARCH), true); + NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("10.0.0.1"), INVALID), false); + NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("1.2.3.4"), IN_SEARCH), true); NS_TEST_ASSERT_EQUAL (rtable.DeleteRoute(Ipv4Address("5.5.5.5")), false); RoutingTableEntry rt4 (/*output device*/dev, /*dst*/Ipv4Address("5.5.5.5"), /*validSeqNo*/false, /*seqNo*/0, /*interface*/iface, /*hop*/15, /*next hop*/Ipv4Address("1.1.1.1"), /*lifetime*/Seconds(-10)); NS_TEST_ASSERT_EQUAL (rtable.AddRoute (rt4), true); - NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("5.5.5.5"), RTF_DOWN), true); + NS_TEST_ASSERT_EQUAL (rtable.SetEntryState(Ipv4Address("5.5.5.5"), INVALID), true); NS_TEST_ASSERT_EQUAL (rtable.LookupRoute(Ipv4Address("5.5.5.5"), rt), false); NS_TEST_ASSERT_EQUAL (rtable.MarkLinkAsUinidirectional(Ipv4Address("1.2.3.4"), Seconds(2)), true); @@ -447,7 +452,7 @@ AodvRtableTest::RunTests () unreachable.insert (std::make_pair(Ipv4Address("4.3.2.1"), 3)); rtable.InvalidateRoutesWithDst(unreachable); NS_TEST_ASSERT_EQUAL (rtable.LookupRoute(Ipv4Address("4.3.2.1"), rt), true); - NS_TEST_ASSERT_EQUAL (rt.GetFlag(), RTF_DOWN); + NS_TEST_ASSERT_EQUAL (rt.GetFlag(), INVALID); rtable.GetListOfDestinationWithNextHop(Ipv4Address("1.1.1.1"), unreachable); NS_TEST_ASSERT_EQUAL (unreachable.size (), 1); NS_TEST_ASSERT_EQUAL (rtable.DeleteRoute(Ipv4Address("1.2.3.4")), true); diff --git a/src/routing/aodv/aodv-rtable.h b/src/routing/aodv/aodv-rtable.h index d97f92af4..5d2a0e422 100644 --- a/src/routing/aodv/aodv-rtable.h +++ b/src/routing/aodv/aodv-rtable.h @@ -47,10 +47,11 @@ namespace aodv { */ enum RouteFlags { - RTF_DOWN = 0, //!< RTF_DOWN - RTF_UP = 1, //!< RTF_UP - RTF_IN_REPAIR = 2,//!< RTF_IN_REPAIR - RTF_IN_SEARCH = 3 //!< RTF_IN_SEARCH + VALID = 0, //!< VALID + INVALID = 1, //!< INVALID + IN_SEARCH = 2, //!< IN_SEARCH + REPAIRABLE = 3, //!< REPAIRABLE + BEING_REPAIRED = 4, //!BEING_REPAIRED }; /**