logic checking in progress

This commit is contained in:
Borovkova Elena
2009-07-23 22:11:23 +04:00
parent 901fbd8cba
commit 5baccd07dc
5 changed files with 184 additions and 89 deletions

View File

@@ -116,22 +116,33 @@ RoutingProtocol::LookupNeighbor (Ipv4Address addr, Neighbor & n)
PurgeNeighbor ();
for (std::vector<Neighbor>::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<Neighbor>::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<Neighbor>::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<NetDevice> 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<Ipv4Route>
@@ -244,8 +259,7 @@ RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, uint32_t
NS_LOG_FUNCTION (this << p->GetUid() << header.GetDestination());
Ptr<Ipv4Route> route;
Ipv4Address dst = header.GetDestination ();
Ptr<NetDevice> 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<Packet> 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<Packet> 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<const Packet> p, const Ipv4Header &header, Ptr<
{
Ptr<Ipv4Route> 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> 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> 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<Packet> p)
RoutingProtocol::RecvError (Ptr<Packet> p, Ipv4Address src)
{
RerrHeader rerrHeader;
p->RemoveHeader(rerrHeader);
for(uint8_t i = 0; i < rerrHeader.GetDestCount(); ++i)
std::map<Ipv4Address, uint32_t> dstWithNextHopSrc;
std::map<Ipv4Address, uint32_t> unreachable;
m_routingTable.GetListOfDestinationWithNextHop(src, dstWithNextHopSrc);
std::pair<Ipv4Address, uint32_t> un;
while (rerrHeader.RemoveUnDestination(un))
{
// TODO
if (IsNeighbor (un.first)) SendRerrWhenBreaksLinkToNextHop (un.first);
else
{
for (std::map<Ipv4Address, uint32_t>::const_iterator i = dstWithNextHopSrc.begin(); i != dstWithNextHopSrc.end(); ++i)
if (i->first == un.first) unreachable.insert(un);
}
}
std::vector<Ipv4Address> precursors;
for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin (); i != unreachable.end ();)
{
if (!rerrHeader.AddUnDestination (i->first, i->second))
{
TypeHeader typeHeader (AODVTYPE_RERR);
Ptr<Packet> packet = Create<Packet> ();
packet->AddHeader (rerrHeader);
packet->AddHeader (typeHeader);
SendRerrMessage (packet, precursors);
rerrHeader.Clear();
}
else
{
Ptr<NetDevice> 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<Ipv4Address> precursors;
std::map<Ipv4Address, RoutingTableEntry> unreachable;
std::map<Ipv4Address, uint32_t> unreachable;
Ptr<NetDevice> 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<Ipv4Address, RoutingTableEntry>::const_iterator i = unreachable.begin (); i != unreachable.end (); ++i)
m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable);
for (std::map<Ipv4Address, uint32_t>::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> packet = Create<Packet> ();
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> packet, std::vector<Ipv4Address> p
m_routingTable.LookupRoute (precursors.front (), toPrecursor);
Ptr<Socket> 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<Ipv4Address> ifaces;
Ptr<NetDevice> dev;
RoutingTableEntry toPrecursor (dev);
for (std::vector<Ipv4Address>::const_iterator i = precursors.begin (); i != precursors.end (); ++i)
{
m_routingTable.LookupRoute (*i, toPrecursor);
bool result = true;
for (std::vector<Ipv4Address>::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<Ipv4Address>::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
{
Ptr<Socket> socket = FindSocketWithInterfaceAddress (*i);
socket->Send (packet);
}
// Should only transmit RERR on those interfaces which have precursor nodes for the broken route
std::vector<Ipv4Address> ifaces;
Ptr<NetDevice> dev;
RoutingTableEntry toPrecursor (dev);
for (std::vector<Ipv4Address>::const_iterator i = precursors.begin (); i != precursors.end (); ++i)
{
if (!m_routingTable.LookupRoute (*i, toPrecursor)) break;
bool result = true;
for (std::vector<Ipv4Address>::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<Ipv4Address>::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
{
Ptr<Socket> socket = FindSocketWithInterfaceAddress (*i);
socket->Send (packet);
}
}
Ptr<Socket>
@@ -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()
}
//-----------------------------------------------------------------------------

View File

@@ -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<Neighbor> m_nb;
//\}
@@ -168,6 +169,8 @@ private:
/// Routing table
RoutingTable m_routingTable;
/// Routing entry for desired destination
std::vector<RoutingTableEntry> 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<Packet> p, Ipv4Address receiver, Ipv4Address src, Ptr<Socket> socket);
/// Receive RREP
void RecvReply (Ptr<Packet> p, Ipv4Address my ,Ipv4Address src);
/// Receive RERR
void RecvError (Ptr<Packet> p);
/// Receive RERR from node with address src
void RecvError (Ptr<Packet> p, Ipv4Address src);
//\}
///\name Send
@@ -253,6 +256,8 @@ private:
void RouteCacheTimerExpire ();
Timer lrtimer;
void LocalRepairTimerExpire ();
Timer m_routeRequestTimer;
void RouteRequestTimerExpire(Ipv4Address dst);
//\}
};

View File

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

View File

@@ -48,11 +48,6 @@ RoutingTableEntry::RoutingTableEntry(Ptr<NetDevice> 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<Ipv4Address> & 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<Ipv4Address, RoutingTableEntry>::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<Ipv4Address, RoutingTableEntry> unreachable, Time badLinkLifetime)
RoutingTable::GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> unreachable)
{
unreachable.clear();
for(std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end(); ++i)
{
for(std::map<Ipv4Address, RoutingTableEntry>::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<Ipv4Address, uint32_t> & unreachable, Time badLinkLifetime)
{
Purge (badLinkLifetime);
for(std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin(); i != m_ipv4AddressEntry.end(); ++i)
{
for(std::map<Ipv4Address, uint32_t>::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<Ipv4Address, RoutingTableEntry>::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;
}
}

View File

@@ -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<NetDevice> dev,Ipv4Address dst = Ipv4Address(), bool vSeqNo = false, u_int32_t m_seqNo = 0, Ipv4Address iface = Ipv4Address(), u_int16_t hops = 0,
RoutingTableEntry(Ptr<NetDevice> 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<Ipv4Address> 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<Ipv4Address, uint32_t> 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<Ipv4Address, RoutingTableEntry> unreachable, Time badLinkLifetime);
/// Delete all outdated entries
void Purge();
void InvalidateRoutesWithDst(std::map<Ipv4Address, uint32_t> 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;