A Discrete-Event Network Simulator
API
aodv-rtable.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 IITP RAS
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Based on
18  * NS-2 AODV model developed by the CMU/MONARCH group and optimized and
19  * tuned by Samir Das and Mahesh Marina, University of Cincinnati;
20  *
21  * AODV-UU implementation by Erik Nordström of Uppsala University
22  * https://web.archive.org/web/20100527072022/http://core.it.uu.se/core/index.php/AODV-UU
23  *
24  * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
25  * Pavel Boyko <boyko@iitp.ru>
26  */
27 
28 #include "aodv-rtable.h"
29 
30 #include "ns3/log.h"
31 #include "ns3/simulator.h"
32 
33 #include <algorithm>
34 #include <iomanip>
35 
36 namespace ns3
37 {
38 
39 NS_LOG_COMPONENT_DEFINE("AodvRoutingTable");
40 
41 namespace aodv
42 {
43 
44 /*
45  The Routing Table
46  */
47 
49  Ipv4Address dst,
50  bool vSeqNo,
51  uint32_t seqNo,
53  uint16_t hops,
54  Ipv4Address nextHop,
55  Time lifetime)
56  : m_ackTimer(Timer::CANCEL_ON_DESTROY),
57  m_validSeqNo(vSeqNo),
58  m_seqNo(seqNo),
59  m_hops(hops),
60  m_lifeTime(lifetime + Simulator::Now()),
61  m_iface(iface),
62  m_flag(VALID),
63  m_reqCount(0),
64  m_blackListState(false),
65  m_blackListTimeout(Simulator::Now())
66 {
67  m_ipv4Route = Create<Ipv4Route>();
68  m_ipv4Route->SetDestination(dst);
69  m_ipv4Route->SetGateway(nextHop);
70  m_ipv4Route->SetSource(m_iface.GetLocal());
71  m_ipv4Route->SetOutputDevice(dev);
72 }
73 
75 {
76 }
77 
78 bool
80 {
81  NS_LOG_FUNCTION(this << id);
82  if (!LookupPrecursor(id))
83  {
84  m_precursorList.push_back(id);
85  return true;
86  }
87  else
88  {
89  return false;
90  }
91 }
92 
93 bool
95 {
96  NS_LOG_FUNCTION(this << id);
97  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin();
98  i != m_precursorList.end();
99  ++i)
100  {
101  if (*i == id)
102  {
103  NS_LOG_LOGIC("Precursor " << id << " found");
104  return true;
105  }
106  }
107  NS_LOG_LOGIC("Precursor " << id << " not found");
108  return false;
109 }
110 
111 bool
113 {
114  NS_LOG_FUNCTION(this << id);
115  std::vector<Ipv4Address>::iterator i =
116  std::remove(m_precursorList.begin(), m_precursorList.end(), id);
117  if (i == m_precursorList.end())
118  {
119  NS_LOG_LOGIC("Precursor " << id << " not found");
120  return false;
121  }
122  else
123  {
124  NS_LOG_LOGIC("Precursor " << id << " found");
125  m_precursorList.erase(i, m_precursorList.end());
126  }
127  return true;
128 }
129 
130 void
132 {
133  NS_LOG_FUNCTION(this);
134  m_precursorList.clear();
135 }
136 
137 bool
139 {
140  return m_precursorList.empty();
141 }
142 
143 void
144 RoutingTableEntry::GetPrecursors(std::vector<Ipv4Address>& prec) const
145 {
146  NS_LOG_FUNCTION(this);
147  if (IsPrecursorListEmpty())
148  {
149  return;
150  }
151  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin();
152  i != m_precursorList.end();
153  ++i)
154  {
155  bool result = true;
156  for (std::vector<Ipv4Address>::const_iterator j = prec.begin(); j != prec.end(); ++j)
157  {
158  if (*j == *i)
159  {
160  result = false;
161  }
162  }
163  if (result)
164  {
165  prec.push_back(*i);
166  }
167  }
168 }
169 
170 void
172 {
173  NS_LOG_FUNCTION(this << badLinkLifetime.As(Time::S));
174  if (m_flag == INVALID)
175  {
176  return;
177  }
178  m_flag = INVALID;
179  m_reqCount = 0;
180  m_lifeTime = badLinkLifetime + Simulator::Now();
181 }
182 
183 void
185 {
186  std::ostream* os = stream->GetStream();
187  // Copy the current ostream state
188  std::ios oldState(nullptr);
189  oldState.copyfmt(*os);
190 
191  *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
192 
193  std::ostringstream dest;
194  std::ostringstream gw;
195  std::ostringstream iface;
196  std::ostringstream expire;
197  dest << m_ipv4Route->GetDestination();
198  gw << m_ipv4Route->GetGateway();
199  iface << m_iface.GetLocal();
200  expire << std::setprecision(2) << (m_lifeTime - Simulator::Now()).As(unit);
201  *os << std::setw(16) << dest.str();
202  *os << std::setw(16) << gw.str();
203  *os << std::setw(16) << iface.str();
204  *os << std::setw(16);
205  switch (m_flag)
206  {
207  case VALID: {
208  *os << "UP";
209  break;
210  }
211  case INVALID: {
212  *os << "DOWN";
213  break;
214  }
215  case IN_SEARCH: {
216  *os << "IN_SEARCH";
217  break;
218  }
219  }
220 
221  *os << std::setw(16) << expire.str();
222  *os << m_hops << std::endl;
223  // Restore the previous ostream state
224  (*os).copyfmt(oldState);
225 }
226 
227 /*
228  The Routing Table
229  */
230 
232  : m_badLinkLifetime(t)
233 {
234 }
235 
236 bool
238 {
239  NS_LOG_FUNCTION(this << id);
240  Purge();
241  if (m_ipv4AddressEntry.empty())
242  {
243  NS_LOG_LOGIC("Route to " << id << " not found; m_ipv4AddressEntry is empty");
244  return false;
245  }
246  std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.find(id);
247  if (i == m_ipv4AddressEntry.end())
248  {
249  NS_LOG_LOGIC("Route to " << id << " not found");
250  return false;
251  }
252  rt = i->second;
253  NS_LOG_LOGIC("Route to " << id << " found");
254  return true;
255 }
256 
257 bool
259 {
260  NS_LOG_FUNCTION(this << id);
261  if (!LookupRoute(id, rt))
262  {
263  NS_LOG_LOGIC("Route to " << id << " not found");
264  return false;
265  }
266  NS_LOG_LOGIC("Route to " << id << " flag is "
267  << ((rt.GetFlag() == VALID) ? "valid" : "not valid"));
268  return (rt.GetFlag() == VALID);
269 }
270 
271 bool
273 {
274  NS_LOG_FUNCTION(this << dst);
275  Purge();
276  if (m_ipv4AddressEntry.erase(dst) != 0)
277  {
278  NS_LOG_LOGIC("Route deletion to " << dst << " successful");
279  return true;
280  }
281  NS_LOG_LOGIC("Route deletion to " << dst << " not successful");
282  return false;
283 }
284 
285 bool
287 {
288  NS_LOG_FUNCTION(this);
289  Purge();
290  if (rt.GetFlag() != IN_SEARCH)
291  {
292  rt.SetRreqCnt(0);
293  }
294  std::pair<std::map<Ipv4Address, RoutingTableEntry>::iterator, bool> result =
295  m_ipv4AddressEntry.insert(std::make_pair(rt.GetDestination(), rt));
296  return result.second;
297 }
298 
299 bool
301 {
302  NS_LOG_FUNCTION(this);
303  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
305  if (i == m_ipv4AddressEntry.end())
306  {
307  NS_LOG_LOGIC("Route update to " << rt.GetDestination() << " fails; not found");
308  return false;
309  }
310  i->second = rt;
311  if (i->second.GetFlag() != IN_SEARCH)
312  {
313  NS_LOG_LOGIC("Route update to " << rt.GetDestination() << " set RreqCnt to 0");
314  i->second.SetRreqCnt(0);
315  }
316  return true;
317 }
318 
319 bool
321 {
322  NS_LOG_FUNCTION(this);
323  std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.find(id);
324  if (i == m_ipv4AddressEntry.end())
325  {
326  NS_LOG_LOGIC("Route set entry state to " << id << " fails; not found");
327  return false;
328  }
329  i->second.SetFlag(state);
330  i->second.SetRreqCnt(0);
331  NS_LOG_LOGIC("Route set entry state to " << id << ": new state is " << state);
332  return true;
333 }
334 
335 void
337  std::map<Ipv4Address, uint32_t>& unreachable)
338 {
339  NS_LOG_FUNCTION(this);
340  Purge();
341  unreachable.clear();
342  for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.begin();
343  i != m_ipv4AddressEntry.end();
344  ++i)
345  {
346  if (i->second.GetNextHop() == nextHop)
347  {
348  NS_LOG_LOGIC("Unreachable insert " << i->first << " " << i->second.GetSeqNo());
349  unreachable.insert(std::make_pair(i->first, i->second.GetSeqNo()));
350  }
351  }
352 }
353 
354 void
355 RoutingTable::InvalidateRoutesWithDst(const std::map<Ipv4Address, uint32_t>& unreachable)
356 {
357  NS_LOG_FUNCTION(this);
358  Purge();
359  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin();
360  i != m_ipv4AddressEntry.end();
361  ++i)
362  {
363  for (std::map<Ipv4Address, uint32_t>::const_iterator j = unreachable.begin();
364  j != unreachable.end();
365  ++j)
366  {
367  if ((i->first == j->first) && (i->second.GetFlag() == VALID))
368  {
369  NS_LOG_LOGIC("Invalidate route with destination address " << i->first);
370  i->second.Invalidate(m_badLinkLifetime);
371  }
372  }
373  }
374 }
375 
376 void
378 {
379  NS_LOG_FUNCTION(this);
380  if (m_ipv4AddressEntry.empty())
381  {
382  return;
383  }
384  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin();
385  i != m_ipv4AddressEntry.end();)
386  {
387  if (i->second.GetInterface() == iface)
388  {
389  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
390  ++i;
391  m_ipv4AddressEntry.erase(tmp);
392  }
393  else
394  {
395  ++i;
396  }
397  }
398 }
399 
400 void
402 {
403  NS_LOG_FUNCTION(this);
404  if (m_ipv4AddressEntry.empty())
405  {
406  return;
407  }
408  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin();
409  i != m_ipv4AddressEntry.end();)
410  {
411  if (i->second.GetLifeTime() < Seconds(0))
412  {
413  if (i->second.GetFlag() == INVALID)
414  {
415  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
416  ++i;
417  m_ipv4AddressEntry.erase(tmp);
418  }
419  else if (i->second.GetFlag() == VALID)
420  {
421  NS_LOG_LOGIC("Invalidate route with destination address " << i->first);
422  i->second.Invalidate(m_badLinkLifetime);
423  ++i;
424  }
425  else
426  {
427  ++i;
428  }
429  }
430  else
431  {
432  ++i;
433  }
434  }
435 }
436 
437 void
438 RoutingTable::Purge(std::map<Ipv4Address, RoutingTableEntry>& table) const
439 {
440  NS_LOG_FUNCTION(this);
441  if (table.empty())
442  {
443  return;
444  }
445  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = table.begin(); i != table.end();)
446  {
447  if (i->second.GetLifeTime() < Seconds(0))
448  {
449  if (i->second.GetFlag() == INVALID)
450  {
451  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
452  ++i;
453  table.erase(tmp);
454  }
455  else if (i->second.GetFlag() == VALID)
456  {
457  NS_LOG_LOGIC("Invalidate route with destination address " << i->first);
458  i->second.Invalidate(m_badLinkLifetime);
459  ++i;
460  }
461  else
462  {
463  ++i;
464  }
465  }
466  else
467  {
468  ++i;
469  }
470  }
471 }
472 
473 bool
475 {
476  NS_LOG_FUNCTION(this << neighbor << blacklistTimeout.As(Time::S));
477  std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.find(neighbor);
478  if (i == m_ipv4AddressEntry.end())
479  {
480  NS_LOG_LOGIC("Mark link unidirectional to " << neighbor << " fails; not found");
481  return false;
482  }
483  i->second.SetUnidirectional(true);
484  i->second.SetBlacklistTimeout(blacklistTimeout);
485  i->second.SetRreqCnt(0);
486  NS_LOG_LOGIC("Set link to " << neighbor << " to unidirectional");
487  return true;
488 }
489 
490 void
491 RoutingTable::Print(Ptr<OutputStreamWrapper> stream, Time::Unit unit /* = Time::S */) const
492 {
493  std::map<Ipv4Address, RoutingTableEntry> table = m_ipv4AddressEntry;
494  Purge(table);
495  std::ostream* os = stream->GetStream();
496  // Copy the current ostream state
497  std::ios oldState(nullptr);
498  oldState.copyfmt(*os);
499 
500  *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
501  *os << "\nAODV Routing table\n";
502  *os << std::setw(16) << "Destination";
503  *os << std::setw(16) << "Gateway";
504  *os << std::setw(16) << "Interface";
505  *os << std::setw(16) << "Flag";
506  *os << std::setw(16) << "Expire";
507  *os << "Hops" << std::endl;
508  for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = table.begin();
509  i != table.end();
510  ++i)
511  {
512  i->second.Print(stream, unit);
513  }
514  *stream->GetStream() << "\n";
515 }
516 
517 } // namespace aodv
518 } // namespace ns3
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
a class to store IPv4 address information on an interface
Ipv4Address GetLocal() const
Get the local address.
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Control the scheduling of simulation events.
Definition: simulator.h:68
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
@ S
second
Definition: nstime.h:116
A simple virtual Timer class.
Definition: timer.h:74
Routing table entry.
Definition: aodv-rtable.h:62
void DeleteAllPrecursors()
Delete all precursors.
Definition: aodv-rtable.cc:131
Ipv4InterfaceAddress m_iface
Output interface address.
Definition: aodv-rtable.h:403
std::vector< Ipv4Address > m_precursorList
List of precursors.
Definition: aodv-rtable.h:408
bool IsPrecursorListEmpty() const
Check that precursor list is empty.
Definition: aodv-rtable.cc:138
bool InsertPrecursor(Ipv4Address id)
Insert precursor in precursor list if it doesn't yet exist in the list.
Definition: aodv-rtable.cc:79
void Print(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print packet to trace file.
Definition: aodv-rtable.cc:184
void GetPrecursors(std::vector< Ipv4Address > &prec) const
Inserts precursors in output parameter prec if they do not yet exist in vector.
Definition: aodv-rtable.cc:144
RouteFlags GetFlag() const
Get the route flags.
Definition: aodv-rtable.h:294
uint16_t m_hops
Hop Count (number of hops needed to reach destination)
Definition: aodv-rtable.h:387
Ptr< Ipv4Route > m_ipv4Route
Ip route, include.
Definition: aodv-rtable.h:401
bool DeletePrecursor(Ipv4Address id)
Delete precursor.
Definition: aodv-rtable.cc:112
void SetRreqCnt(uint8_t n)
Set the RREQ count.
Definition: aodv-rtable.h:303
void Invalidate(Time badLinkLifetime)
Mark entry as "down" (i.e.
Definition: aodv-rtable.cc:171
bool LookupPrecursor(Ipv4Address id)
Lookup precursor by address.
Definition: aodv-rtable.cc:94
Ipv4Address GetDestination() const
Get destination address function.
Definition: aodv-rtable.h:132
~RoutingTableEntry()
Definition: aodv-rtable.cc:74
RoutingTableEntry(Ptr< NetDevice > dev=nullptr, Ipv4Address dst=Ipv4Address(), bool vSeqNo=false, uint32_t seqNo=0, Ipv4InterfaceAddress iface=Ipv4InterfaceAddress(), uint16_t hops=0, Ipv4Address nextHop=Ipv4Address(), Time lifetime=Simulator::Now())
constructor
Definition: aodv-rtable.cc:48
Time m_lifeTime
Expiration or deletion time of the route Lifetime field in the routing table plays dual role: for an ...
Definition: aodv-rtable.h:394
RouteFlags m_flag
Routing flags: valid, invalid or in search.
Definition: aodv-rtable.h:405
uint8_t m_reqCount
Number of route requests.
Definition: aodv-rtable.h:412
void GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map< Ipv4Address, uint32_t > &unreachable)
Lookup routing entries with next hop Address dst and not empty list of precursors.
Definition: aodv-rtable.cc:336
bool LookupValidRoute(Ipv4Address dst, RoutingTableEntry &rt)
Lookup route in VALID state.
Definition: aodv-rtable.cc:258
void Purge()
Delete all outdated entries and invalidate valid entry if Lifetime is expired.
Definition: aodv-rtable.cc:401
bool Update(RoutingTableEntry &rt)
Update routing table.
Definition: aodv-rtable.cc:300
Time m_badLinkLifetime
Deletion time for invalid routes.
Definition: aodv-rtable.h:543
bool AddRoute(RoutingTableEntry &r)
Add routing table entry if it doesn't yet exist in routing table.
Definition: aodv-rtable.cc:286
void Print(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print routing table.
Definition: aodv-rtable.cc:491
RoutingTable(Time t)
constructor
Definition: aodv-rtable.cc:231
bool LookupRoute(Ipv4Address dst, RoutingTableEntry &rt)
Lookup routing table entry with destination address dst.
Definition: aodv-rtable.cc:237
bool SetEntryState(Ipv4Address dst, RouteFlags state)
Set routing table entry flags.
Definition: aodv-rtable.cc:320
void DeleteAllRoutesFromInterface(Ipv4InterfaceAddress iface)
Delete all route from interface with address iface.
Definition: aodv-rtable.cc:377
void InvalidateRoutesWithDst(const std::map< Ipv4Address, uint32_t > &unreachable)
Update routing entries with this destination as follows:
Definition: aodv-rtable.cc:355
std::map< Ipv4Address, RoutingTableEntry > m_ipv4AddressEntry
The routing table.
Definition: aodv-rtable.h:541
bool MarkLinkAsUnidirectional(Ipv4Address neighbor, Time blacklistTimeout)
Mark entry as unidirectional (e.g.
Definition: aodv-rtable.cc:474
bool DeleteRoute(Ipv4Address dst)
Delete routing table entry with destination address dst, if it exists.
Definition: aodv-rtable.cc:272
RouteFlags
Route record states.
Definition: aodv-rtable.h:51
@ INVALID
INVALID.
Definition: aodv-rtable.h:53
@ IN_SEARCH
IN_SEARCH.
Definition: aodv-rtable.h:54
@ VALID
VALID.
Definition: aodv-rtable.h:52
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Every class exported by the ns3 library is enclosed in the ns3 namespace.