A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
aodv-rtable.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 IITP RAS
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Based on
19  * NS-2 AODV model developed by the CMU/MONARCH group and optimized and
20  * tuned by Samir Das and Mahesh Marina, University of Cincinnati;
21  *
22  * AODV-UU implementation by Erik Nordström of Uppsala University
23  * http://core.it.uu.se/core/index.php/AODV-UU
24  *
25  * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
26  * Pavel Boyko <boyko@iitp.ru>
27  */
28 
29 #include "aodv-rtable.h"
30 #include <algorithm>
31 #include <iomanip>
32 #include "ns3/simulator.h"
33 #include "ns3/log.h"
34 
35 NS_LOG_COMPONENT_DEFINE ("AodvRoutingTable");
36 
37 namespace ns3
38 {
39 namespace aodv
40 {
41 
42 /*
43  The Routing Table
44  */
45 
46 RoutingTableEntry::RoutingTableEntry (Ptr<NetDevice> dev, Ipv4Address dst, bool vSeqNo, uint32_t seqNo,
47  Ipv4InterfaceAddress iface, uint16_t hops, Ipv4Address nextHop, Time lifetime) :
48  m_ackTimer (Timer::CANCEL_ON_DESTROY),
49  m_validSeqNo (vSeqNo), m_seqNo (seqNo), m_hops (hops),
50  m_lifeTime (lifetime + Simulator::Now ()), m_iface (iface), m_flag (VALID),
51  m_reqCount (0), m_blackListState (false), m_blackListTimeout (Simulator::Now ())
52 {
53  m_ipv4Route = Create<Ipv4Route> ();
55  m_ipv4Route->SetGateway (nextHop);
58 }
59 
61 {
62 }
63 
64 bool
66 {
67  NS_LOG_FUNCTION (this << id);
68  if (!LookupPrecursor (id))
69  {
70  m_precursorList.push_back (id);
71  return true;
72  }
73  else
74  return false;
75 }
76 
77 bool
79 {
80  NS_LOG_FUNCTION (this << id);
81  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
82  != m_precursorList.end (); ++i)
83  {
84  if (*i == id)
85  {
86  NS_LOG_LOGIC ("Precursor " << id << " found");
87  return true;
88  }
89  }
90  NS_LOG_LOGIC ("Precursor " << id << " not found");
91  return false;
92 }
93 
94 bool
96 {
97  NS_LOG_FUNCTION (this << id);
98  std::vector<Ipv4Address>::iterator i = std::remove (m_precursorList.begin (),
99  m_precursorList.end (), id);
100  if (i == m_precursorList.end ())
101  {
102  NS_LOG_LOGIC ("Precursor " << id << " not found");
103  return false;
104  }
105  else
106  {
107  NS_LOG_LOGIC ("Precursor " << id << " found");
108  m_precursorList.erase (i, m_precursorList.end ());
109  }
110  return true;
111 }
112 
113 void
115 {
116  NS_LOG_FUNCTION (this);
117  m_precursorList.clear ();
118 }
119 
120 bool
122 {
123  return m_precursorList.empty ();
124 }
125 
126 void
127 RoutingTableEntry::GetPrecursors (std::vector<Ipv4Address> & prec) const
128 {
129  NS_LOG_FUNCTION (this);
130  if (IsPrecursorListEmpty ())
131  return;
132  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
133  != m_precursorList.end (); ++i)
134  {
135  bool result = true;
136  for (std::vector<Ipv4Address>::const_iterator j = prec.begin (); j
137  != prec.end (); ++j)
138  {
139  if (*j == *i)
140  result = false;
141  }
142  if (result)
143  prec.push_back (*i);
144  }
145 }
146 
147 void
149 {
150  NS_LOG_FUNCTION (this << badLinkLifetime.GetSeconds ());
151  if (m_flag == INVALID)
152  return;
153  m_flag = INVALID;
154  m_reqCount = 0;
155  m_lifeTime = badLinkLifetime + Simulator::Now ();
156 }
157 
158 void
160 {
161  std::ostream* os = stream->GetStream ();
162  *os << m_ipv4Route->GetDestination () << "\t" << m_ipv4Route->GetGateway ()
163  << "\t" << m_iface.GetLocal () << "\t";
164  switch (m_flag)
165  {
166  case VALID:
167  {
168  *os << "UP";
169  break;
170  }
171  case INVALID:
172  {
173  *os << "DOWN";
174  break;
175  }
176  case IN_SEARCH:
177  {
178  *os << "IN_SEARCH";
179  break;
180  }
181  }
182  *os << "\t";
183  *os << std::setiosflags (std::ios::fixed) <<
184  std::setiosflags (std::ios::left) << std::setprecision (2) <<
185  std::setw (14) << (m_lifeTime - Simulator::Now ()).GetSeconds ();
186  *os << "\t" << m_hops << "\n";
187 }
188 
189 /*
190  The Routing Table
191  */
192 
194  m_badLinkLifetime (t)
195 {
196 }
197 
198 bool
200 {
201  NS_LOG_FUNCTION (this << id);
202  Purge ();
203  if (m_ipv4AddressEntry.empty ())
204  {
205  NS_LOG_LOGIC ("Route to " << id << " not found; m_ipv4AddressEntry is empty");
206  return false;
207  }
208  std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
209  m_ipv4AddressEntry.find (id);
210  if (i == m_ipv4AddressEntry.end ())
211  {
212  NS_LOG_LOGIC ("Route to " << id << " not found");
213  return false;
214  }
215  rt = i->second;
216  NS_LOG_LOGIC ("Route to " << id << " found");
217  return true;
218 }
219 
220 bool
222 {
223  NS_LOG_FUNCTION (this << id);
224  if (!LookupRoute (id, rt))
225  {
226  NS_LOG_LOGIC ("Route to " << id << " not found");
227  return false;
228  }
229  NS_LOG_LOGIC ("Route to " << id << " flag is " << ((rt.GetFlag () == VALID) ? "valid" : "not valid"));
230  return (rt.GetFlag () == VALID);
231 }
232 
233 bool
235 {
236  NS_LOG_FUNCTION (this << dst);
237  Purge ();
238  if (m_ipv4AddressEntry.erase (dst) != 0)
239  {
240  NS_LOG_LOGIC ("Route deletion to " << dst << " successful");
241  return true;
242  }
243  NS_LOG_LOGIC ("Route deletion to " << dst << " not successful");
244  return false;
245 }
246 
247 bool
249 {
250  NS_LOG_FUNCTION (this);
251  Purge ();
252  if (rt.GetFlag () != IN_SEARCH)
253  rt.SetRreqCnt (0);
254  std::pair<std::map<Ipv4Address, RoutingTableEntry>::iterator, bool> result =
255  m_ipv4AddressEntry.insert (std::make_pair (rt.GetDestination (), rt));
256  return result.second;
257 }
258 
259 bool
261 {
262  NS_LOG_FUNCTION (this);
263  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
264  m_ipv4AddressEntry.find (rt.GetDestination ());
265  if (i == m_ipv4AddressEntry.end ())
266  {
267  NS_LOG_LOGIC ("Route update to " << rt.GetDestination () << " fails; not found");
268  return false;
269  }
270  i->second = rt;
271  if (i->second.GetFlag () != IN_SEARCH)
272  {
273  NS_LOG_LOGIC ("Route update to " << rt.GetDestination () << " set RreqCnt to 0");
274  i->second.SetRreqCnt (0);
275  }
276  return true;
277 }
278 
279 bool
281 {
282  NS_LOG_FUNCTION (this);
283  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
284  m_ipv4AddressEntry.find (id);
285  if (i == m_ipv4AddressEntry.end ())
286  {
287  NS_LOG_LOGIC ("Route set entry state to " << id << " fails; not found");
288  return false;
289  }
290  i->second.SetFlag (state);
291  i->second.SetRreqCnt (0);
292  NS_LOG_LOGIC ("Route set entry state to " << id << ": new state is " << state);
293  return true;
294 }
295 
296 void
297 RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable )
298 {
299  NS_LOG_FUNCTION (this);
300  Purge ();
301  unreachable.clear ();
302  for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
303  m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
304  {
305  if (i->second.GetNextHop () == nextHop)
306  {
307  NS_LOG_LOGIC ("Unreachable insert " << i->first << " " << i->second.GetSeqNo ());
308  unreachable.insert (std::make_pair (i->first, i->second.GetSeqNo ()));
309  }
310  }
311 }
312 
313 void
314 RoutingTable::InvalidateRoutesWithDst (const std::map<Ipv4Address, uint32_t> & unreachable)
315 {
316  NS_LOG_FUNCTION (this);
317  Purge ();
318  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
319  m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
320  {
321  for (std::map<Ipv4Address, uint32_t>::const_iterator j =
322  unreachable.begin (); j != unreachable.end (); ++j)
323  {
324  if ((i->first == j->first) && (i->second.GetFlag () == VALID))
325  {
326  NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
327  i->second.Invalidate (m_badLinkLifetime);
328  }
329  }
330  }
331 }
332 
333 void
335 {
336  NS_LOG_FUNCTION (this);
337  if (m_ipv4AddressEntry.empty ())
338  return;
339  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
340  m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end ();)
341  {
342  if (i->second.GetInterface () == iface)
343  {
344  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
345  ++i;
346  m_ipv4AddressEntry.erase (tmp);
347  }
348  else
349  ++i;
350  }
351 }
352 
353 void
355 {
356  NS_LOG_FUNCTION (this);
357  if (m_ipv4AddressEntry.empty ())
358  return;
359  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
360  m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end ();)
361  {
362  if (i->second.GetLifeTime () < Seconds (0))
363  {
364  if (i->second.GetFlag () == INVALID)
365  {
366  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
367  ++i;
368  m_ipv4AddressEntry.erase (tmp);
369  }
370  else if (i->second.GetFlag () == VALID)
371  {
372  NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
373  i->second.Invalidate (m_badLinkLifetime);
374  ++i;
375  }
376  else
377  ++i;
378  }
379  else
380  {
381  ++i;
382  }
383  }
384 }
385 
386 void
387 RoutingTable::Purge (std::map<Ipv4Address, RoutingTableEntry> &table) const
388 {
389  NS_LOG_FUNCTION (this);
390  if (table.empty ())
391  return;
392  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
393  table.begin (); i != table.end ();)
394  {
395  if (i->second.GetLifeTime () < Seconds (0))
396  {
397  if (i->second.GetFlag () == INVALID)
398  {
399  std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
400  ++i;
401  table.erase (tmp);
402  }
403  else if (i->second.GetFlag () == VALID)
404  {
405  NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
406  i->second.Invalidate (m_badLinkLifetime);
407  ++i;
408  }
409  else
410  ++i;
411  }
412  else
413  {
414  ++i;
415  }
416  }
417 }
418 
419 bool
421 {
422  NS_LOG_FUNCTION (this << neighbor << blacklistTimeout.GetSeconds ());
423  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
424  m_ipv4AddressEntry.find (neighbor);
425  if (i == m_ipv4AddressEntry.end ())
426  {
427  NS_LOG_LOGIC ("Mark link unidirectional to " << neighbor << " fails; not found");
428  return false;
429  }
430  i->second.SetUnidirectional (true);
431  i->second.SetBalcklistTimeout (blacklistTimeout);
432  i->second.SetRreqCnt (0);
433  NS_LOG_LOGIC ("Set link to " << neighbor << " to unidirectional");
434  return true;
435 }
436 
437 void
439 {
440  std::map<Ipv4Address, RoutingTableEntry> table = m_ipv4AddressEntry;
441  Purge (table);
442  *stream->GetStream () << "\nAODV Routing table\n"
443  << "Destination\tGateway\t\tInterface\tFlag\tExpire\t\tHops\n";
444  for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
445  table.begin (); i != table.end (); ++i)
446  {
447  i->second.Print (stream);
448  }
449  *stream->GetStream () << "\n";
450 }
451 
452 }
453 }