NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
readvertise.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2019, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "readvertise.hpp"
27 #include "core/logger.hpp"
28 #include "core/random.hpp"
29 
30 namespace nfd {
31 namespace rib {
32 
34 
35 const time::milliseconds Readvertise::RETRY_DELAY_MIN = 50_s;
36 const time::milliseconds Readvertise::RETRY_DELAY_MAX = 3600_s;
37 
38 static time::milliseconds
39 randomizeTimer(time::milliseconds baseTimer)
40 {
41  std::uniform_int_distribution<uint64_t> dist(-5, 5);
42  time::milliseconds newTime = baseTimer + time::milliseconds(dist(getGlobalRng()));
43  return std::max(newTime, 0_ms);
44 }
45 
47  unique_ptr<ReadvertisePolicy> policy,
48  unique_ptr<ReadvertiseDestination> destination)
49  : m_scheduler(scheduler)
50  , m_policy(std::move(policy))
51  , m_destination(std::move(destination))
52 {
53  m_addRouteConn = rib.afterAddRoute.connect([this] (const auto& r) { this->afterAddRoute(r); });
54  m_removeRouteConn = rib.beforeRemoveRoute.connect([this] (const auto& r) { this->beforeRemoveRoute(r); });
55 
56  m_destination->afterAvailabilityChange.connect([this] (bool isAvailable) {
57  if (isAvailable) {
58  this->afterDestinationAvailable();
59  }
60  else {
61  this->afterDestinationUnavailable();
62  }
63  });
64 }
65 
66 void
67 Readvertise::afterAddRoute(const RibRouteRef& ribRoute)
68 {
69  optional<ReadvertiseAction> action = m_policy->handleNewRoute(ribRoute);
70  if (!action) {
71  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
72  ',' << ribRoute.route->origin << ") not-readvertising");
73  return;
74  }
75 
77  bool isNew = false;
78  std::tie(rrIt, isNew) = m_rrs.emplace(action->prefix);
79 
80  if (!isNew && rrIt->signer != action->signer) {
81  NFD_LOG_WARN("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
82  ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
83  " old-signer " << rrIt->signer << " new-signer " << action->signer);
84  }
85  rrIt->signer = action->signer;
86 
87  RouteRrIndex::iterator indexIt;
88  std::tie(indexIt, isNew) = m_routeToRr.emplace(ribRoute, rrIt);
89  BOOST_ASSERT(isNew);
90 
91  if (rrIt->nRibRoutes++ > 0) {
92  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
93  ',' << ribRoute.route->origin << ") already-readvertised-as " << action->prefix);
94  return;
95  }
96 
97  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
98  ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
99  " signer " << action->signer);
100  rrIt->retryDelay = RETRY_DELAY_MIN;
101  this->advertise(rrIt);
102 }
103 
104 void
105 Readvertise::beforeRemoveRoute(const RibRouteRef& ribRoute)
106 {
107  auto indexIt = m_routeToRr.find(ribRoute);
108  if (indexIt == m_routeToRr.end()) {
109  NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
110  ',' << ribRoute.route->origin << ") not-readvertised");
111  return;
112  }
113 
114  auto rrIt = indexIt->second;
115  m_routeToRr.erase(indexIt);
116 
117  if (--rrIt->nRibRoutes > 0) {
118  NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
119  ',' << ribRoute.route->origin << ") needed-by " << rrIt->nRibRoutes);
120  return;
121  }
122 
123  rrIt->retryDelay = RETRY_DELAY_MIN;
124  this->withdraw(rrIt);
125 }
126 
127 void
128 Readvertise::afterDestinationAvailable()
129 {
130  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end(); ++rrIt) {
131  rrIt->retryDelay = RETRY_DELAY_MIN;
132  this->advertise(rrIt);
133  }
134 }
135 
136 void
137 Readvertise::afterDestinationUnavailable()
138 {
139  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end();) {
140  if (rrIt->nRibRoutes > 0) {
141  rrIt->retryEvt.cancel(); // stop retrying or refreshing
142  ++rrIt;
143  }
144  else {
145  rrIt = m_rrs.erase(rrIt); // assume withdraw has completed
146  }
147  }
148 }
149 
150 void
151 Readvertise::advertise(ReadvertisedRouteContainer::iterator rrIt)
152 {
153  BOOST_ASSERT(rrIt->nRibRoutes > 0);
154 
155  if (!m_destination->isAvailable()) {
156  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " destination-unavailable");
157  return;
158  }
159 
160  m_destination->advertise(*rrIt,
161  [=] {
162  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
163  rrIt->retryDelay = RETRY_DELAY_MIN;
164  rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(m_policy->getRefreshInterval()),
165  [=] { advertise(rrIt); });
166  },
167  [=] (const std::string& msg) {
168  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " failure " << msg);
169  rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
170  rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(rrIt->retryDelay),
171  [=] { advertise(rrIt); });
172  });
173 }
174 
175 void
176 Readvertise::withdraw(ReadvertisedRouteContainer::iterator rrIt)
177 {
178  BOOST_ASSERT(rrIt->nRibRoutes == 0);
179 
180  if (!m_destination->isAvailable()) {
181  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " destination-unavailable");
182  m_rrs.erase(rrIt);
183  return;
184  }
185 
186  m_destination->withdraw(*rrIt,
187  [=] {
188  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " success");
189  m_rrs.erase(rrIt);
190  },
191  [=] (const std::string& msg) {
192  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
193  rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
194  rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(rrIt->retryDelay),
195  [=] { withdraw(rrIt); });
196  });
197 }
198 
199 } // namespace rib
200 } // namespace nfd
Readvertise(Rib &rib, ndn::util::Scheduler &scheduler, unique_ptr< ReadvertisePolicy > policy, unique_ptr< ReadvertiseDestination > destination)
Definition: readvertise.cpp:46
Declares the global pseudorandom number generator (PRNG) for NFD.
represents the Routing Information Base
Definition: rib.hpp:59
#define NFD_LOG_WARN
Definition: logger.hpp:40
ndn::util::signal::Signal< Rib, RibRouteRef > afterAddRoute
signals after a Route is added
Definition: rib.hpp:246
RibEntry::const_iterator route
Definition: rib.hpp:46
references a route
Definition: rib.hpp:43
EventId scheduleEvent(time::nanoseconds after, const EventCallback &callback)
Schedule a one-time event after the specified delay.
Definition: scheduler.cpp:103
Table::const_iterator iterator
Definition: cs-internal.hpp:41
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
shared_ptr< RibEntry > entry
Definition: rib.hpp:45
readvertise a subset of routes to a destination according to a policy
Definition: readvertise.hpp:44
static time::milliseconds randomizeTimer(time::milliseconds baseTimer)
Definition: readvertise.cpp:39
std::mt19937 & getGlobalRng()
Definition: random.cpp:32
#define NFD_LOG_DEBUG
Definition: logger.hpp:38
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
ndn::util::signal::Signal< Rib, RibRouteRef > beforeRemoveRoute
signals before a route is removed
Definition: rib.hpp:250