A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
dsr-rcache.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Yufei Cheng
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Yufei Cheng <yfcheng@ittc.ku.edu>
7 * Song Luan <lsuper@mail.ustc.edu.cn> (Implemented Link Cache using Dijsktra
8 * algorithm)
9 *
10 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
11 * ResiliNets Research Group https://resilinets.org/
12 * Information and Telecommunication Technology Center (ITTC)
13 * and Department of Electrical Engineering and Computer Science
14 * The University of Kansas Lawrence, KS USA.
15 *
16 * Work supported in part by NSF FIND (Future Internet Design) Program
17 * under grant CNS-0626918 (Postmodern Internet Architecture),
18 * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
19 * US Department of Defense (DoD), and ITTC at The University of Kansas.
20 */
21
22#include "dsr-rcache.h"
23
24#include "ns3/address-utils.h"
25#include "ns3/ipv4-route.h"
26#include "ns3/log.h"
27#include "ns3/packet.h"
28#include "ns3/simulator.h"
29#include "ns3/socket.h"
30#include "ns3/wifi-mac-header.h"
31
32#include <algorithm>
33#include <cmath>
34#include <functional>
35#include <iomanip>
36#include <iostream>
37#include <list>
38#include <map>
39#include <vector>
40
41namespace ns3
42{
43
44NS_LOG_COMPONENT_DEFINE("DsrRouteCache");
45
46namespace dsr
47{
48
49/**
50 * @ingroup dsr
51 * @brief Compare route cache entries by hop count and priority,
52 * equivalent to comparing the expire time.
53 * @param a The first route cache entry
54 * @param b The second route canche entry
55 * @returns `true` if `a < b`
56 */
57bool
59{
60 // compare based on both with hop count considered priority
61 return (a.GetVector().size() < b.GetVector().size()) ||
62 ((a.GetVector().size() == b.GetVector().size()) &&
63 (a.GetExpireTime() > b.GetExpireTime()));
64}
65
66/**
67 * @ingroup dsr
68 * @brief Compare route cache entries by hop count only
69 * @param a The first route cache entry
70 * @param b The second route canche entry
71 * @returns `true` if `a < b`
72 */
73bool
75{
76 // compare based on hops
77 return a.GetVector().size() < b.GetVector().size();
78}
79
80/**
81 * @ingroup dsr
82 * @brief Compare route cache entries by hop priority only.
83 * @param a The first route cache entry
84 * @param b The second route canche entry
85 * @returns `true` if `a < b`
86 */
87bool
89{
90 // compare based on expire time
91 return a.GetExpireTime() > b.GetExpireTime();
92}
93
94void
96{
97 NS_LOG_DEBUG(m_low << "----" << m_high);
98}
99
101 : m_nodeStability(nodeStab + Simulator::Now())
102{
103}
104
108
110 : m_linkStability(linkStab + Simulator::Now())
111{
112}
113
117
118void
120{
121 NS_LOG_LOGIC("LifeTime: " << GetLinkStability().As(Time::S));
122}
123
124typedef std::list<DsrRouteCacheEntry>::value_type route_pair;
125
127 : m_ackTimer(Timer::CANCEL_ON_DESTROY),
128 m_dst(dst),
129 m_path(ip),
130 m_expire(exp + Simulator::Now()),
131 m_reqCount(0),
132 m_blackListState(false),
134{
135}
136
140
141void
143{
144 m_reqCount = 0;
145 m_expire = badLinkLifetime + Simulator::Now();
146}
147
148void
149DsrRouteCacheEntry::Print(std::ostream& os) const
150{
151 os << m_dst << "\t" << (m_expire - Simulator::Now()).As(Time::S) << "\t";
152}
153
155
156TypeId
158{
159 static TypeId tid = TypeId("ns3::dsr::DsrRouteCache")
160 .SetParent<Object>()
161 .SetGroupName("Dsr")
162 .AddConstructor<DsrRouteCache>();
163 return tid;
164}
165
167 : m_vector(0),
169 m_isLinkCache(false),
170 m_ntimer(Timer::CANCEL_ON_DESTROY),
172{
173 /*
174 * The timer to set layer 2 notification, not fully supported by ns3 yet
175 */
176 m_ntimer.SetDelay(m_delay);
177 m_ntimer.SetFunction(&DsrRouteCache::PurgeMac, this);
178}
179
181{
183 // clear the route cache when done
184 m_sortedRoutes.clear();
185}
186
187void
188DsrRouteCache::RemoveLastEntry(std::list<DsrRouteCacheEntry>& rtVector)
189{
190 NS_LOG_FUNCTION(this);
191 // Release the last entry of route list
192 rtVector.pop_back();
193}
194
195bool
197{
198 NS_LOG_FUNCTION(this << dst);
199 auto i = m_sortedRoutes.find(dst);
200 if (i == m_sortedRoutes.end())
201 {
202 NS_LOG_LOGIC("Failed to find the route entry for the destination " << dst);
203 return false;
204 }
205 else
206 {
207 std::list<DsrRouteCacheEntry> rtVector = i->second;
208 DsrRouteCacheEntry successEntry = rtVector.front();
209 successEntry.SetExpireTime(RouteCacheTimeout);
210 rtVector.pop_front();
211 rtVector.push_back(successEntry);
212 rtVector.sort(CompareRoutesExpire); // sort the route vector first
213 m_sortedRoutes.erase(dst); // erase the entry first
214 /*
215 * Save the new route cache along with the destination address in map
216 */
217 auto result = m_sortedRoutes.insert(std::make_pair(dst, rtVector));
218 return result.second;
219 }
220 return false;
221}
222
223bool
225{
226 NS_LOG_FUNCTION(this << id);
227 if (IsLinkCache())
228 {
229 return LookupRoute_Link(id, rt);
230 }
231
232 Purge(); // Purge first to remove expired entries
233 if (m_sortedRoutes.empty())
234 {
235 NS_LOG_LOGIC("Route to " << id << " not found; m_sortedRoutes is empty");
236 return false;
237 }
238 auto i = m_sortedRoutes.find(id);
239 if (i == m_sortedRoutes.end())
240 {
241 NS_LOG_LOGIC("No Direct Route to " << id << " found");
242 for (auto j = m_sortedRoutes.begin(); j != m_sortedRoutes.end(); ++j)
243 {
244 std::list<DsrRouteCacheEntry> rtVector =
245 j->second; // The route cache vector linked with destination address
246 /*
247 * Loop through the possibly multiple routes within the route vector
248 */
249 for (auto k = rtVector.begin(); k != rtVector.end(); ++k)
250 {
251 // return the first route in the route vector
254
255 for (auto l = routeVector.begin(); l != routeVector.end(); ++l)
256 {
257 changeVector.push_back(*l);
258
259 if (*l == id)
260 {
261 break;
262 }
263 }
264 /*
265 * When the changed vector is smaller in size and larger than 1, which means we
266 * have found a route with the destination address we are looking for
267 */
268 if ((changeVector.size() < routeVector.size()) && (changeVector.size() > 1))
269 {
270 DsrRouteCacheEntry changeEntry; // Create the route entry
271 changeEntry.SetVector(changeVector);
272 changeEntry.SetDestination(id);
273 // Use the expire time from original route entry
274 changeEntry.SetExpireTime(k->GetExpireTime());
275 // We need to add new route entry here
276 std::list<DsrRouteCacheEntry> newVector;
277 newVector.push_back(changeEntry);
278 newVector.sort(CompareRoutesExpire); // sort the route vector first
279 m_sortedRoutes[id] =
280 newVector; // Only get the first sub route and add it in route cache
281 NS_LOG_INFO("We have a sub-route to " << id << " add it in route cache");
282 }
283 }
284 }
285 }
286 NS_LOG_INFO("Here we check the route cache again after updated the sub routes");
287 auto m = m_sortedRoutes.find(id);
288 if (m == m_sortedRoutes.end())
289 {
290 NS_LOG_LOGIC("No updated route till last time");
291 return false;
292 }
293 /*
294 * We have a direct route to the destination address
295 */
296 std::list<DsrRouteCacheEntry> rtVector = m->second;
297 rt = rtVector.front(); // use the first entry in the route vector
298 NS_LOG_LOGIC("Route to " << id << " with route size " << rtVector.size());
299 return true;
300}
301
302void
304{
305 NS_LOG_FUNCTION(this << type);
306 if (type == "LinkCache")
307 {
308 m_isLinkCache = true;
309 }
310 else if (type == "PathCache")
311 {
312 m_isLinkCache = false;
313 }
314 else
315 {
316 m_isLinkCache = true; // use link cache as default
317 NS_LOG_INFO("Error Cache Type");
318 }
319}
320
321bool
327
328void
330{
331 NS_LOG_FUNCTION(this << source);
332 /**
333 * @brief The following are initialize-single-source
334 */
335 // @d shortest-path estimate
336 std::map<Ipv4Address, uint32_t> d;
337 // @pre preceding node
338 std::map<Ipv4Address, Ipv4Address> pre;
339 for (auto i = m_netGraph.begin(); i != m_netGraph.end(); ++i)
340 {
341 if (i->second.find(source) != i->second.end())
342 {
343 d[i->first] = i->second[source];
344 pre[i->first] = source;
345 }
346 else
347 {
348 d[i->first] = MAXWEIGHT;
349 pre[i->first] = Ipv4Address("255.255.255.255");
350 }
351 }
352 d[source] = 0;
353 /**
354 * @brief The following is the core of Dijkstra algorithm
355 */
356 // the node set which shortest distance has been calculated, if true calculated
357 std::map<Ipv4Address, bool> s;
358 double temp = MAXWEIGHT;
359 Ipv4Address tempip("255.255.255.255");
360 for (uint32_t i = 0; i < m_netGraph.size(); i++)
361 {
362 temp = MAXWEIGHT;
363 for (auto j = d.begin(); j != d.end(); ++j)
364 {
365 Ipv4Address ip = j->first;
366 if (s.find(ip) == s.end())
367 {
368 /*
369 * @brief The following are for comparison
370 */
371 if (j->second <= temp)
372 {
373 temp = j->second;
374 tempip = ip;
375 }
376 }
377 }
378 if (!tempip.IsBroadcast())
379 {
380 s[tempip] = true;
381 for (auto k = m_netGraph[tempip].begin(); k != m_netGraph[tempip].end(); ++k)
382 {
383 if (s.find(k->first) == s.end() && d[k->first] > d[tempip] + k->second)
384 {
385 d[k->first] = d[tempip] + k->second;
386 pre[k->first] = tempip;
387 }
388 /*
389 * Selects the shortest-length route that has the longest expected lifetime
390 * (highest minimum timeout of any link in the route)
391 * For the computation overhead and complexity
392 * Here I just implement kind of greedy strategy to select link with the longest
393 * expected lifetime when there is two options
394 */
395 else if (d[k->first] == d[tempip] + k->second)
396 {
397 auto oldlink = m_linkCache.find(Link(k->first, pre[k->first]));
398 auto newlink = m_linkCache.find(Link(k->first, tempip));
399 if (oldlink != m_linkCache.end() && newlink != m_linkCache.end())
400 {
401 if (oldlink->second.GetLinkStability() < newlink->second.GetLinkStability())
402 {
403 NS_LOG_INFO("Select the link with longest expected lifetime");
404 d[k->first] = d[tempip] + k->second;
405 pre[k->first] = tempip;
406 }
407 }
408 else
409 {
410 NS_LOG_INFO("Link Stability Info Corrupt");
411 }
412 }
413 }
414 }
415 }
416 // clean the best route table
418 for (auto i = pre.begin(); i != pre.end(); ++i)
419 {
420 // loop for all vertices
422 Ipv4Address iptemp = i->first;
423
424 if (!i->second.IsBroadcast() && iptemp != source)
425 {
426 while (iptemp != source)
427 {
428 route.push_back(iptemp);
429 iptemp = pre[iptemp];
430 }
431 route.push_back(source);
432 // Reverse the route
433 DsrRouteCacheEntry::IP_VECTOR reverseroute(route.rbegin(), route.rend());
434 NS_LOG_LOGIC("Add newly calculated best routes");
435 PrintVector(reverseroute);
436 m_bestRoutesTable_link[i->first] = reverseroute;
437 }
438 }
439}
440
441bool
443{
444 NS_LOG_FUNCTION(this << id);
445 /// We need to purge the link node cache
447 auto i = m_bestRoutesTable_link.find(id);
448 if (i == m_bestRoutesTable_link.end())
449 {
450 NS_LOG_INFO("No route find to " << id);
451 return false;
452 }
453
454 if (i->second.size() < 2)
455 {
456 NS_LOG_LOGIC("Route to " << id << " error");
457 return false;
458 }
459
460 DsrRouteCacheEntry newEntry; // Create the route entry
461 newEntry.SetVector(i->second);
462 newEntry.SetDestination(id);
464 NS_LOG_INFO("Route to " << id << " found with the length " << i->second.size());
465 rt = newEntry;
466 std::vector<Ipv4Address> path = rt.GetVector();
467 PrintVector(path);
468 return true;
469}
470
471void
473{
474 NS_LOG_FUNCTION(this);
475 for (auto i = m_linkCache.begin(); i != m_linkCache.end();)
476 {
477 NS_LOG_DEBUG("The link stability " << i->second.GetLinkStability().As(Time::S));
478 auto itmp = i;
479 if (i->second.GetLinkStability().IsNegative())
480 {
481 ++i;
482 m_linkCache.erase(itmp);
483 }
484 else
485 {
486 ++i;
487 }
488 }
489 /// may need to remove them after verify
490 for (auto i = m_nodeCache.begin(); i != m_nodeCache.end();)
491 {
492 NS_LOG_DEBUG("The node stability " << i->second.GetNodeStability().As(Time::S));
493 auto itmp = i;
494 if (i->second.GetNodeStability().IsNegative())
495 {
496 ++i;
497 m_nodeCache.erase(itmp);
498 }
499 else
500 {
501 ++i;
502 }
503 }
504}
505
506void
508{
509 NS_LOG_FUNCTION(this);
510 m_netGraph.clear();
511 for (auto i = m_linkCache.begin(); i != m_linkCache.end(); ++i)
512 {
513 // Here the weight is set as 1
514 /// @todo May need to set different weight for different link here later
515 uint32_t weight = 1;
516 m_netGraph[i->first.m_low][i->first.m_high] = weight;
517 m_netGraph[i->first.m_high][i->first.m_low] = weight;
518 }
519}
520
521bool
523{
524 NS_LOG_FUNCTION(this << node);
525 auto i = m_nodeCache.find(node);
526 if (i == m_nodeCache.end())
527 {
528 NS_LOG_INFO("The initial stability " << m_initStability.As(Time::S));
530 m_nodeCache[node] = ns;
531 return false;
532 }
533 else
534 {
535 /// @todo get rid of the debug here
536 NS_LOG_INFO("The node stability " << i->second.GetNodeStability().As(Time::S));
537 NS_LOG_INFO("The stability here "
538 << Time(i->second.GetNodeStability() * m_stabilityIncrFactor).As(Time::S));
539 DsrNodeStab ns(Time(i->second.GetNodeStability() * m_stabilityIncrFactor));
540 m_nodeCache[node] = ns;
541 return true;
542 }
543 return false;
544}
545
546bool
548{
549 NS_LOG_FUNCTION(this << node);
550 auto i = m_nodeCache.find(node);
551 if (i == m_nodeCache.end())
552 {
554 m_nodeCache[node] = ns;
555 return false;
556 }
557 else
558 {
559 /// @todo remove it here
560 NS_LOG_INFO("The stability here " << i->second.GetNodeStability().As(Time::S));
561 NS_LOG_INFO("The stability here "
562 << Time(i->second.GetNodeStability() / m_stabilityDecrFactor).As(Time::S));
563 DsrNodeStab ns(Time(i->second.GetNodeStability() / m_stabilityDecrFactor));
564 m_nodeCache[node] = ns;
565 return true;
566 }
567 return false;
568}
569
570bool
572{
573 NS_LOG_FUNCTION(this << source);
574 NS_LOG_LOGIC("Use Link Cache");
575 /// Purge the link node cache first
577 for (uint32_t i = 0; i < nodelist.size() - 1; i++)
578 {
579 DsrNodeStab ns; /// This is the node stability
581
582 if (m_nodeCache.find(nodelist[i]) == m_nodeCache.end())
583 {
584 m_nodeCache[nodelist[i]] = ns;
585 }
586 if (m_nodeCache.find(nodelist[i + 1]) == m_nodeCache.end())
587 {
588 m_nodeCache[nodelist[i + 1]] = ns;
589 }
590 Link link(nodelist[i], nodelist[i + 1]); /// Link represent the one link for the route
591 DsrLinkStab stab; /// Link stability
593 /// Set the link stability as the smallest node stability
594 if (m_nodeCache[nodelist[i]].GetNodeStability() <
595 m_nodeCache[nodelist[i + 1]].GetNodeStability())
596 {
597 stab.SetLinkStability(m_nodeCache[nodelist[i]].GetNodeStability());
598 }
599 else
600 {
601 stab.SetLinkStability(m_nodeCache[nodelist[i + 1]].GetNodeStability());
602 }
603 if (stab.GetLinkStability() < m_minLifeTime)
604 {
605 NS_LOG_LOGIC("Stability: " << stab.GetLinkStability().As(Time::S));
606 /// Set the link stability as the m)minLifeTime, default is 1 second
608 }
609 m_linkCache[link] = stab;
610 NS_LOG_DEBUG("Add a new link");
611 link.Print();
612 NS_LOG_DEBUG("Link Info");
613 stab.Print();
614 }
616 RebuildBestRouteTable(source);
617 return true;
618}
619
620void
622{
623 NS_LOG_FUNCTION(this);
624 /// Purge the link node cache first
626 if (rt.size() < 2)
627 {
628 NS_LOG_INFO("The route is too short");
629 return;
630 }
631 for (auto i = rt.begin(); i != rt.end() - 1; ++i)
632 {
633 Link link(*i, *(i + 1));
634 if (m_linkCache.find(link) != m_linkCache.end())
635 {
636 if (m_linkCache[link].GetLinkStability() < m_useExtends)
637 {
638 m_linkCache[link].SetLinkStability(m_useExtends);
639 /// @todo remove after debug
640 NS_LOG_INFO("The time of the link "
641 << m_linkCache[link].GetLinkStability().As(Time::S));
642 }
643 }
644 else
645 {
646 NS_LOG_INFO("We cannot find a link in cache");
647 }
648 }
649 /// Increase the stability of the node cache
650 for (auto i = rt.begin(); i != rt.end(); ++i)
651 {
652 if (m_nodeCache.find(*i) != m_nodeCache.end())
653 {
654 NS_LOG_LOGIC("Increase the stability");
655 if (m_nodeCache[*i].GetNodeStability() <= m_initStability)
656 {
657 IncStability(*i);
658 }
659 else
660 {
661 NS_LOG_INFO("The node stability has already been increased");
662 }
663 }
664 }
665}
666
667bool
669{
670 NS_LOG_FUNCTION(this);
671 Purge();
672 std::list<DsrRouteCacheEntry> rtVector; // Declare the route cache entry vector
673 Ipv4Address dst = rt.GetDestination();
674 std::vector<Ipv4Address> route = rt.GetVector();
675
676 NS_LOG_DEBUG("The route destination we have " << dst);
677 auto i = m_sortedRoutes.find(dst);
678
679 if (i == m_sortedRoutes.end())
680 {
681 rtVector.push_back(rt);
682 m_sortedRoutes.erase(dst); // Erase the route entries for dst first
683 /**
684 * Save the new route cache along with the destination address in map
685 */
686 auto result = m_sortedRoutes.insert(std::make_pair(dst, rtVector));
687 return result.second;
688 }
689
690 rtVector = i->second;
691 NS_LOG_DEBUG("The existing route size " << rtVector.size() << " for destination address "
692 << dst);
693 /**
694 * @brief Drop the most aged packet when buffer reaches to max
695 */
696 if (rtVector.size() >= m_maxEntriesEachDst)
697 {
698 RemoveLastEntry(rtVector); // Drop the last entry for the sorted route cache, the route
699 // has already been sorted
700 }
701
702 if (FindSameRoute(rt, rtVector))
703 {
705 "Find same vector, the FindSameRoute function will update the route expire time");
706 return true;
707 }
708 else
709 {
710 // Check if the expire time for the new route has expired or not
712 {
713 rtVector.push_back(rt);
714 // This sort function will sort the route cache entries based on the size of route
715 // in each of the route entries
716 rtVector.sort(CompareRoutesExpire);
717 NS_LOG_DEBUG("The first time" << rtVector.front().GetExpireTime().As(Time::S)
718 << " The second time "
719 << rtVector.back().GetExpireTime().As(Time::S));
720 NS_LOG_DEBUG("The first hop" << rtVector.front().GetVector().size()
721 << " The second hop "
722 << rtVector.back().GetVector().size());
723 m_sortedRoutes.erase(dst); // erase the route entries for dst first
724 /**
725 * Save the new route cache along with the destination address in map
726 */
727 auto result = m_sortedRoutes.insert(std::make_pair(dst, rtVector));
728 return result.second;
729 }
730 else
731 {
732 NS_LOG_INFO("The newly found route is already expired");
733 }
734 }
735
736 return false;
737}
738
739bool
740DsrRouteCache::FindSameRoute(DsrRouteCacheEntry& rt, std::list<DsrRouteCacheEntry>& rtVector)
741{
742 NS_LOG_FUNCTION(this);
743 for (auto i = rtVector.begin(); i != rtVector.end(); ++i)
744 {
745 // return the first route in the route vector
748
749 if (routeVector == newVector)
750 {
751 NS_LOG_DEBUG("Found same routes in the route cache with the vector size "
752 << rt.GetDestination() << " " << rtVector.size());
753 NS_LOG_DEBUG("The new route expire time " << rt.GetExpireTime().As(Time::S)
754 << " the original expire time "
755 << i->GetExpireTime().As(Time::S));
756 if (rt.GetExpireTime() > i->GetExpireTime())
757 {
758 i->SetExpireTime(rt.GetExpireTime());
759 }
760 m_sortedRoutes.erase(rt.GetDestination()); // erase the entry first
761 rtVector.sort(CompareRoutesExpire); // sort the route vector first
762 /*
763 * Save the new route cache along with the destination address in map
764 */
765 auto result = m_sortedRoutes.insert(std::make_pair(rt.GetDestination(), rtVector));
766 return result.second;
767 }
768 }
769 return false;
770}
771
772bool
774{
775 NS_LOG_FUNCTION(this << dst);
776 Purge(); // purge the route cache first to remove timeout entries
777 if (m_sortedRoutes.erase(dst) != 0)
778 {
779 NS_LOG_LOGIC("Route deletion to " << dst << " successful");
780 return true;
781 }
782 NS_LOG_LOGIC("Route deletion to " << dst << " not successful");
783 return false;
784}
785
786void
788 Ipv4Address unreachNode,
789 Ipv4Address node)
790{
791 NS_LOG_FUNCTION(this << errorSrc << unreachNode << node);
792 if (IsLinkCache())
793 {
794 // Purge the link node cache first
796 /*
797 * The following are for cleaning the broken link in link cache
798 * We basically remove the link between errorSrc and unreachNode
799 */
800 Link link1(errorSrc, unreachNode);
801 Link link2(unreachNode, errorSrc);
802 // erase the two kind of links to make sure the link is removed from the link cache
803 NS_LOG_DEBUG("Erase the route");
804 m_linkCache.erase(link1);
805 /// @todo get rid of this one
806 NS_LOG_DEBUG("The link cache size " << m_linkCache.size());
807 m_linkCache.erase(link2);
808 NS_LOG_DEBUG("The link cache size " << m_linkCache.size());
809
810 auto i = m_nodeCache.find(errorSrc);
811 if (i == m_nodeCache.end())
812 {
813 NS_LOG_LOGIC("Update the node stability unsuccessfully");
814 }
815 else
816 {
817 DecStability(i->first);
818 }
819 i = m_nodeCache.find(unreachNode);
820 if (i == m_nodeCache.end())
821 {
822 NS_LOG_LOGIC("Update the node stability unsuccessfully");
823 }
824 else
825 {
826 DecStability(i->first);
827 }
830 }
831 else
832 {
833 /*
834 * the following are for cleaning the broken link in pathcache
835 *
836 */
837 Purge();
838 if (m_sortedRoutes.empty())
839 {
840 return;
841 }
842 /*
843 * Loop all the routes saved in the route cache
844 */
845 for (auto j = m_sortedRoutes.begin(); j != m_sortedRoutes.end();)
846 {
847 auto jtmp = j;
848 Ipv4Address address = j->first;
849 std::list<DsrRouteCacheEntry> rtVector = j->second;
850 /*
851 * Loop all the routes for a single destination
852 */
853 for (auto k = rtVector.begin(); k != rtVector.end();)
854 {
855 // return the first route in the route vector
858 /*
859 * Loop the ip addresses within a single route entry
860 */
861 for (auto i = routeVector.begin(); i != routeVector.end(); ++i)
862 {
863 if (*i != errorSrc)
864 {
865 changeVector.push_back(*i);
866 }
867 else
868 {
869 changeVector.push_back(*i);
870
871 if (*(i + 1) == unreachNode)
872 {
873 break;
874 }
875 }
876 }
877 /*
878 * Verify if need to remove some affected links
879 */
880 if (changeVector.size() == routeVector.size())
881 {
882 NS_LOG_DEBUG("The route does not contain the broken link");
883 ++k;
884 }
885 else if ((changeVector.size() < routeVector.size()) && (changeVector.size() > 1))
886 {
887 NS_LOG_DEBUG("sub route " << m_subRoute);
888 if (m_subRoute)
889 {
890 Time expire = k->GetExpireTime();
891 /*
892 * Remove the route first
893 */
894 k = rtVector.erase(k);
895 DsrRouteCacheEntry changeEntry;
896 changeEntry.SetVector(changeVector);
897 Ipv4Address destination = changeVector.back();
898 NS_LOG_DEBUG("The destination of the newly formed route "
899 << destination << " and the size of the route "
900 << changeVector.size());
901 changeEntry.SetDestination(destination);
902 changeEntry.SetExpireTime(
903 expire); // Initialize the timeout value to the one it has
904 rtVector.push_back(changeEntry); // Add the route entry to the route list
905 NS_LOG_DEBUG("We have a sub-route to " << destination);
906 }
907 else
908 {
909 /*
910 * Remove the route
911 */
912 k = rtVector.erase(k);
913 }
914 }
915 else
916 {
917 NS_LOG_LOGIC("Cut route unsuccessful and erase the route");
918 /*
919 * Remove the route
920 */
921 k = rtVector.erase(k);
922 }
923 }
924 ++j;
925 if (!IsLinkCache())
926 {
927 m_sortedRoutes.erase(jtmp);
928 }
929 if (!rtVector.empty())
930 {
931 /*
932 * Save the new route cache along with the destination address in map
933 */
934 rtVector.sort(CompareRoutesExpire);
935 m_sortedRoutes[address] = rtVector;
936 }
937 else
938 {
939 NS_LOG_DEBUG("There is no route left for that destination " << address);
940 }
941 }
942 }
943}
944
945void
946DsrRouteCache::PrintVector(std::vector<Ipv4Address>& vec)
947{
948 NS_LOG_FUNCTION(this);
949 /*
950 * Check elements in a route vector, used when one wants to check the IP addresses saved in
951 */
952 if (vec.empty())
953 {
954 NS_LOG_DEBUG("The vector is empty");
955 }
956 else
957 {
958 NS_LOG_DEBUG("Print all the elements in a vector");
959 for (auto i = vec.begin(); i != vec.end(); ++i)
960 {
961 NS_LOG_DEBUG("The ip address " << *i);
962 }
963 }
964}
965
966void
967DsrRouteCache::PrintRouteVector(std::list<DsrRouteCacheEntry> route)
968{
969 NS_LOG_FUNCTION(this);
970 for (auto i = route.begin(); i != route.end(); i++)
971 {
972 std::vector<Ipv4Address> path = i->GetVector();
973 NS_LOG_INFO("Route NO. ");
974 PrintVector(path);
975 }
976}
977
978void
980{
981 NS_LOG_FUNCTION(this);
982 // Trying to purge the route cache
983 if (m_sortedRoutes.empty())
984 {
985 NS_LOG_DEBUG("The route cache is empty");
986 return;
987 }
988 for (auto i = m_sortedRoutes.begin(); i != m_sortedRoutes.end();)
989 {
990 // Loop of route cache entry with the route size
991 auto itmp = i;
992 /*
993 * The route cache entry vector
994 */
995 Ipv4Address dst = i->first;
996 std::list<DsrRouteCacheEntry> rtVector = i->second;
997 NS_LOG_DEBUG("The route vector size of 1 " << dst << " " << rtVector.size());
998 if (!rtVector.empty())
999 {
1000 for (auto j = rtVector.begin(); j != rtVector.end();)
1001 {
1002 NS_LOG_DEBUG("The expire time of every entry with expire time "
1003 << j->GetExpireTime());
1004 /*
1005 * First verify if the route has expired or not
1006 */
1007 if (j->GetExpireTime().IsNegative())
1008 {
1009 /*
1010 * When the expire time has passed, erase the certain route
1011 */
1012 NS_LOG_DEBUG("Erase the expired route for " << dst << " with expire time "
1013 << j->GetExpireTime());
1014 j = rtVector.erase(j);
1015 }
1016 else
1017 {
1018 ++j;
1019 }
1020 }
1021 NS_LOG_DEBUG("The route vector size of 2 " << dst << " " << rtVector.size());
1022 if (!rtVector.empty())
1023 {
1024 ++i;
1025 m_sortedRoutes.erase(itmp); // erase the entry first
1026 /*
1027 * Save the new route cache along with the destination address in map
1028 */
1029 m_sortedRoutes.insert(std::make_pair(dst, rtVector));
1030 }
1031 else
1032 {
1033 ++i;
1034 m_sortedRoutes.erase(itmp);
1035 }
1036 }
1037 else
1038 {
1039 ++i;
1040 m_sortedRoutes.erase(itmp);
1041 }
1042 }
1043}
1044
1045void
1046DsrRouteCache::Print(std::ostream& os)
1047{
1048 NS_LOG_FUNCTION(this);
1049 Purge();
1050 os << "\nDSR Route Cache\n"
1051 << "Destination\tGateway\t\tInterface\tFlag\tExpire\tHops\n";
1052 for (auto i = m_routeEntryVector.begin(); i != m_routeEntryVector.end(); ++i)
1053 {
1054 i->Print(os);
1055 }
1056 os << "\n";
1057}
1058
1059// ----------------------------------------------------------------------------------------------------------
1060/**
1061 * This part of code maintains an Acknowledgment id cache for next hop and remove duplicate ids
1062 */
1063uint16_t
1065{
1066 NS_LOG_FUNCTION(this);
1067 auto i = m_ackIdCache.find(nextHop);
1068 if (i == m_ackIdCache.end())
1069 {
1070 NS_LOG_LOGIC("No Ack id for " << nextHop
1071 << " found and use id 1 for the first network ack id");
1072 m_ackIdCache[nextHop] = 1;
1073 return 1;
1074 }
1075
1076 uint16_t ackId = m_ackIdCache[nextHop];
1077 NS_LOG_LOGIC("Ack id for " << nextHop << " found in the cache has value " << ackId);
1078 ackId++;
1079 m_ackIdCache[nextHop] = ackId;
1080 return ackId;
1081}
1082
1083uint16_t
1085{
1086 return m_ackIdCache.size();
1087}
1088
1089// ----------------------------------------------------------------------------------------------------------
1090/**
1091 * This part maintains a neighbor list to handle unidirectional links and link-layer acks
1092 */
1093bool
1095{
1096 NS_LOG_FUNCTION(this);
1097 PurgeMac(); // purge the mac cache
1098 for (auto i = m_nb.begin(); i != m_nb.end(); ++i)
1099 {
1100 if (i->m_neighborAddress == addr)
1101 {
1102 return true;
1103 }
1104 }
1105 return false;
1106}
1107
1108Time
1110{
1111 NS_LOG_FUNCTION(this);
1112 PurgeMac();
1113 for (auto i = m_nb.begin(); i != m_nb.end(); ++i)
1114 {
1115 if (i->m_neighborAddress == addr)
1116 {
1117 return (i->m_expireTime - Simulator::Now());
1118 }
1119 }
1120 return Seconds(0);
1121}
1122
1123void
1124DsrRouteCache::UpdateNeighbor(std::vector<Ipv4Address> nodeList, Time expire)
1125{
1126 NS_LOG_FUNCTION(this);
1127 for (auto i = m_nb.begin(); i != m_nb.end(); ++i)
1128 {
1129 for (auto j = nodeList.begin(); j != nodeList.end(); ++j)
1130 {
1131 if (i->m_neighborAddress == (*j))
1132 {
1133 i->m_expireTime = std::max(expire + Simulator::Now(), i->m_expireTime);
1134 if (i->m_hardwareAddress == Mac48Address())
1135 {
1136 i->m_hardwareAddress = LookupMacAddress(i->m_neighborAddress);
1137 }
1138 return;
1139 }
1140 }
1141 }
1142
1143 Ipv4Address addr;
1144 NS_LOG_LOGIC("Open link to " << addr);
1145 Neighbor neighbor(addr, LookupMacAddress(addr), expire + Simulator::Now());
1146 m_nb.push_back(neighbor);
1147 PurgeMac();
1148}
1149
1150void
1151DsrRouteCache::AddNeighbor(std::vector<Ipv4Address> nodeList, Ipv4Address ownAddress, Time expire)
1152{
1153 NS_LOG_LOGIC("Add neighbor number " << nodeList.size());
1154 for (auto j = nodeList.begin(); j != nodeList.end();)
1155 {
1156 Ipv4Address addr = *j;
1157 if (addr == ownAddress)
1158 {
1159 j = nodeList.erase(j);
1160 NS_LOG_DEBUG("The node list size " << nodeList.size());
1161 }
1162 else
1163 {
1164 ++j;
1165 }
1166 Neighbor neighbor(addr, LookupMacAddress(addr), expire + Simulator::Now());
1167 m_nb.push_back(neighbor);
1168 PurgeMac();
1169 }
1170}
1171
1172/// CloseNeighbor structure
1174{
1175 /**
1176 * Check if the entry is expired
1177 *
1178 * @param nb DsrRouteCache::Neighbor entry
1179 * @return true if expired or closed, false otherwise
1180 */
1182 {
1183 return ((nb.m_expireTime < Simulator::Now()) || nb.close);
1184 }
1185};
1186
1187void
1189{
1190 if (m_nb.empty())
1191 {
1192 return;
1193 }
1194
1195 CloseNeighbor pred;
1196 if (!m_handleLinkFailure.IsNull())
1197 {
1198 for (auto j = m_nb.begin(); j != m_nb.end(); ++j)
1199 {
1200 if (pred(*j))
1201 {
1202 NS_LOG_LOGIC("Close link to " << j->m_neighborAddress);
1203 /// @todo disable temporarily
1204 // m_handleLinkFailure (j->m_neighborAddress);
1205 }
1206 }
1207 }
1208 m_nb.erase(std::remove_if(m_nb.begin(), m_nb.end(), pred), m_nb.end());
1209 m_ntimer.Cancel();
1210 m_ntimer.Schedule();
1211}
1212
1213void
1215{
1216 m_ntimer.Cancel();
1217 m_ntimer.Schedule();
1218}
1219
1220void
1222{
1223 m_arp.push_back(a);
1224}
1225
1226void
1228{
1229 m_arp.erase(std::remove(m_arp.begin(), m_arp.end(), a), m_arp.end());
1230}
1231
1234{
1235 Mac48Address hwaddr;
1236 for (auto i = m_arp.begin(); i != m_arp.end(); ++i)
1237 {
1238 ArpCache::Entry* entry = (*i)->Lookup(addr);
1239 if (entry != nullptr && (entry->IsAlive() || entry->IsPermanent()) && !entry->IsExpired())
1240 {
1241 hwaddr = Mac48Address::ConvertFrom(entry->GetMacAddress());
1242 break;
1243 }
1244 }
1245 return hwaddr;
1246}
1247
1248void
1250{
1251 Mac48Address addr = hdr.GetAddr1();
1252
1253 for (auto i = m_nb.begin(); i != m_nb.end(); ++i)
1254 {
1255 if (i->m_hardwareAddress == addr)
1256 {
1257 i->close = true;
1258 }
1259 }
1260 PurgeMac();
1261}
1262} // namespace dsr
1263} // namespace ns3
return result
A record that that holds information about an ArpCache entry.
Definition arp-cache.h:178
bool IsAlive()
Definition arp-cache.cc:400
Address GetMacAddress() const
Definition arp-cache.cc:502
bool IsExpired() const
Definition arp-cache.cc:549
bool IsPermanent()
Definition arp-cache.cc:414
Ipv4 addresses are stored in host order in this class.
bool IsBroadcast() const
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
Object()
Caller graph was not generated because of its size.
Definition object.cc:93
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
Control the scheduling of simulation events.
Definition simulator.h:57
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:342
@ S
second
Definition nstime.h:107
A simple virtual Timer class.
Definition timer.h:67
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
DsrNodeStab class (DSR node stability).
Definition dsr-rcache.h:181
Time m_nodeStability
the node stability
Definition dsr-rcache.h:210
void SetNodeStability(Time nodeStab)
Set node stability.
Definition dsr-rcache.h:195
DsrNodeStab(Time nodeStab=Simulator::Now())
Constructor.
DsrRouteCacheEntry class for entries in the route cache.
Definition dsr-rcache.h:218
IP_VECTOR GetVector() const
Get the IP vector.
Definition dsr-rcache.h:298
void SetDestination(Ipv4Address d)
Set destination address.
Definition dsr-rcache.h:289
Time m_expire
Expire time for queue entry.
Definition dsr-rcache.h:350
DsrRouteCacheEntry(IP_VECTOR const &ip=IP_VECTOR(), Ipv4Address dst=Ipv4Address(), Time exp=Simulator::Now())
Constructor.
IP_VECTOR m_path
brief The IP address constructed route
Definition dsr-rcache.h:349
Ipv4Address m_dst
The destination Ip address.
Definition dsr-rcache.h:348
uint8_t m_reqCount
Number of route requests.
Definition dsr-rcache.h:352
Timer m_ackTimer
RREP_ACK timer.
Definition dsr-rcache.h:347
Ipv4Address GetDestination() const
Get destination address.
Definition dsr-rcache.h:280
virtual ~DsrRouteCacheEntry()
Time m_blackListTimeout
Time for which the node is put into the blacklist.
Definition dsr-rcache.h:354
void Invalidate(Time badLinkLifetime)
Mark entry as "down" (i.e.
void Print(std::ostream &os) const
Print necessary fields.
std::vector< Ipv4Address > IP_VECTOR
Define the vector to hold Ip address.
Definition dsr-rcache.h:220
bool m_blackListState
Indicate if this entry is in "blacklist".
Definition dsr-rcache.h:353
Time GetExpireTime() const
Get expire time.
Definition dsr-rcache.h:325
void SetExpireTime(Time exp)
Set expire time.
Definition dsr-rcache.h:316
void SetVector(IP_VECTOR v)
Sets the IP vector.
Definition dsr-rcache.h:307
DSR route request queue Since DSR is an on demand routing we queue requests while looking for route.
Definition dsr-rcache.h:365
std::map< Ipv4Address, std::map< Ipv4Address, uint32_t > > m_netGraph
Current network graph state for this node, double is weight, which is calculated by the node informat...
Definition dsr-rcache.h:794
uint32_t m_stabilityDecrFactor
stability decrease factor
Definition dsr-rcache.h:762
std::list< DsrRouteCacheEntry::IP_VECTOR > routeVector
Define the vector of route entries.
Definition dsr-rcache.h:387
static TypeId GetTypeId()
Get the type ID.
void PurgeLinkNode()
Purge from the cache if the stability time expired.
Callback< void, Ipv4Address, uint8_t > m_handleLinkFailure
The following code handles link-layer acks.
Definition dsr-rcache.h:867
std::map< Link, DsrLinkStab > m_linkCache
The data structure to store link info.
Definition dsr-rcache.h:798
void ScheduleTimer()
Schedule m_ntimer.
void RebuildBestRouteTable(Ipv4Address source)
Rebuild the best route table.
void SetCacheType(std::string type)
Dijsktra algorithm to get the best route from m_netGraph and update the m_bestRoutesTable_link when c...
routeEntryVector m_routeEntryVector
Define the route vector.
Definition dsr-rcache.h:775
void AddArpCache(Ptr< ArpCache > a)
Add ARP cache to be used to allow layer 2 notifications processing.
std::map< Ipv4Address, DsrNodeStab > m_nodeCache
The data structure to store node info.
Definition dsr-rcache.h:799
void Purge()
Delete all outdated entries and invalidate valid entry if Lifetime is expired.
Time m_initStability
initial stability
Definition dsr-rcache.h:764
uint16_t CheckUniqueAckId(Ipv4Address nextHop)
Check for duplicate ids and save new entries if the id is not present in the table.
bool IsLinkCache()
is link cached
uint32_t m_stabilityIncrFactor
stability increase factor
Definition dsr-rcache.h:763
bool LookupRoute(Ipv4Address id, DsrRouteCacheEntry &rt)
Lookup route cache entry with destination address dst.
uint16_t GetAckSize()
Get the ack table size.
std::map< Ipv4Address, uint16_t > m_ackIdCache
The id cache to ensure all the ids are unique.
Definition dsr-rcache.h:779
void ProcessTxError(const WifiMacHeader &hdr)
Process layer 2 TX error notification.
Time RouteCacheTimeout
The maximum period of time that dsr is allowed to for an unused route.
Definition dsr-rcache.h:756
bool AddRoute_Link(DsrRouteCacheEntry::IP_VECTOR nodelist, Ipv4Address node)
dd route link to cache
std::vector< Ptr< ArpCache > > m_arp
list of ARP cached to be used for layer 2 notifications processing
Definition dsr-rcache.h:874
Mac48Address LookupMacAddress(Ipv4Address addr)
Find MAC address by IP using list of ARP caches.
void UseExtends(DsrRouteCacheEntry::IP_VECTOR rt)
When a link from the Route Cache is used in routing a packet originated or salvaged by that node,...
void PurgeMac()
Remove all expired mac entries.
bool FindSameRoute(DsrRouteCacheEntry &rt, std::list< DsrRouteCacheEntry > &rtVector)
Find the same route in the route cache.
std::map< Ipv4Address, routeEntryVector > m_sortedRoutes
Map the ipv4Address to route entry vector.
Definition dsr-rcache.h:773
DsrRouteCacheEntry::IP_VECTOR m_vector
The route vector to save the ip addresses for intermediate nodes.
Definition dsr-rcache.h:753
void PrintVector(std::vector< Ipv4Address > &vec)
Print the route vector elements.
bool m_isLinkCache
Check if the route is using path cache or link cache.
Definition dsr-rcache.h:781
Time m_delay
This timeout deals with the passive ack.
Definition dsr-rcache.h:876
bool DeleteRoute(Ipv4Address dst)
Delete the route with certain destination address.
bool IncStability(Ipv4Address node)
increase the stability of the node
void PrintRouteVector(std::list< DsrRouteCacheEntry > route)
Print all the route vector elements from the route list.
uint32_t m_maxEntriesEachDst
number of entries for each destination
Definition dsr-rcache.h:777
Time GetExpireTime(Ipv4Address addr)
Return expire time for neighbor node with address addr, if exists, else return 0.
Time m_useExtends
use extend
Definition dsr-rcache.h:766
std::vector< Neighbor > m_nb
vector of entries
Definition dsr-rcache.h:871
Time m_minLifeTime
minimum lifetime
Definition dsr-rcache.h:765
void DelArpCache(Ptr< ArpCache >)
Don't use the provided ARP cache any more (interface is down).
void Print(std::ostream &os)
Print route cache.
bool LookupRoute_Link(Ipv4Address id, DsrRouteCacheEntry &rt)
used by LookupRoute when LinkCache
bool UpdateRouteEntry(Ipv4Address dst)
Update route cache entry if it has been recently used and successfully delivered the data packet.
void UpdateNeighbor(std::vector< Ipv4Address > nodeList, Time expire)
Update expire time for entry with address addr, if it exists, else add new entry.
void RemoveLastEntry(std::list< DsrRouteCacheEntry > &rtVector)
Remove the aged route cache entries when the route cache is full.
Timer m_ntimer
Timer for neighbor's list. Schedule Purge().
Definition dsr-rcache.h:869
bool m_subRoute
Check if save the sub route entries or not.
Definition dsr-rcache.h:783
void DeleteAllRoutesIncludeLink(Ipv4Address errorSrc, Ipv4Address unreachNode, Ipv4Address node)
Delete all the routes which includes the link from next hop address that has just been notified as un...
bool IsNeighbor(Ipv4Address addr)
Check that node with address addr is neighbor.
std::map< Ipv4Address, DsrRouteCacheEntry::IP_VECTOR > m_bestRoutesTable_link
for link route cache
Definition dsr-rcache.h:797
bool DecStability(Ipv4Address node)
decrease the stability of the node
void UpdateNetGraph()
Update the Net Graph for the link and node cache has changed.
bool AddRoute(DsrRouteCacheEntry &rt)
Add route cache entry if it doesn't yet exist in route cache.
void AddNeighbor(std::vector< Ipv4Address > nodeList, Ipv4Address ownAddress, Time expire)
Add to the neighbor list.
#define MAXWEIGHT
The link cache to update all the link status, bi-link is two link for link is a struct when the weigh...
Definition dsr-rcache.h:788
bool CompareRoutesBoth(const DsrRouteCacheEntry &a, const DsrRouteCacheEntry &b)
Compare route cache entries by hop count and priority, equivalent to comparing the expire time.
Definition dsr-rcache.cc:58
bool CompareRoutesExpire(const DsrRouteCacheEntry &a, const DsrRouteCacheEntry &b)
Compare route cache entries by hop priority only.
Definition dsr-rcache.cc:88
bool CompareRoutesHops(const DsrRouteCacheEntry &a, const DsrRouteCacheEntry &b)
Compare route cache entries by hop count only.
Definition dsr-rcache.cc:74
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:288
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1398
std::list< DsrRouteCacheEntry >::value_type route_pair
Every class exported by the ns3 library is enclosed in the ns3 namespace.
CloseNeighbor structure.
bool operator()(const DsrRouteCache::Neighbor &nb) const
Check if the entry is expired.
Structure to manage neighbor state.
Definition dsr-rcache.h:653
Time m_expireTime
route expire time
Definition dsr-rcache.h:656