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-2018, 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 
33 NFD_LOG_INIT("Readvertise");
34 
35 const time::milliseconds Readvertise::RETRY_DELAY_MIN = time::seconds(50);
36 const time::milliseconds Readvertise::RETRY_DELAY_MAX = time::seconds(3600);
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, time::milliseconds(0));
44 }
45 
46 Readvertise::Readvertise(Rib& rib, unique_ptr<ReadvertisePolicy> policy,
47  unique_ptr<ReadvertiseDestination> destination)
48  : m_policy(std::move(policy))
49  , m_destination(std::move(destination))
50 {
51  m_addRouteConn = rib.afterAddRoute.connect(bind(&Readvertise::afterAddRoute, this, _1));
52  m_removeRouteConn = rib.beforeRemoveRoute.connect(bind(&Readvertise::beforeRemoveRoute, this, _1));
53 
54  m_destination->afterAvailabilityChange.connect([this] (bool isAvailable) {
55  if (isAvailable) {
56  this->afterDestinationAvailable();
57  }
58  else {
59  this->afterDestinationUnavailable();
60  }
61  });
62 }
63 
64 void
65 Readvertise::afterAddRoute(const RibRouteRef& ribRoute)
66 {
67  optional<ReadvertiseAction> action = m_policy->handleNewRoute(ribRoute);
68  if (!action) {
69  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
70  ',' << ribRoute.route->origin << ") not-readvertising");
71  return;
72  }
73 
75  bool isNew = false;
76  std::tie(rrIt, isNew) = m_rrs.emplace(action->prefix);
77 
78  if (!isNew && rrIt->signer != action->signer) {
79  NFD_LOG_WARN("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
80  ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
81  " old-signer " << rrIt->signer << " new-signer " << action->signer);
82  }
83  rrIt->signer = action->signer;
84 
85  RouteRrIndex::iterator indexIt;
86  std::tie(indexIt, isNew) = m_routeToRr.emplace(ribRoute, rrIt);
87  BOOST_ASSERT(isNew);
88 
89  if (rrIt->nRibRoutes++ > 0) {
90  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
91  ',' << ribRoute.route->origin << ") already-readvertised-as " << action->prefix);
92  return;
93  }
94 
95  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
96  ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
97  " signer " << action->signer);
98  rrIt->retryDelay = RETRY_DELAY_MIN;
99  this->advertise(rrIt);
100 }
101 
102 void
103 Readvertise::beforeRemoveRoute(const RibRouteRef& ribRoute)
104 {
105  auto indexIt = m_routeToRr.find(ribRoute);
106  if (indexIt == m_routeToRr.end()) {
107  NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
108  ',' << ribRoute.route->origin << ") not-readvertised");
109  return;
110  }
111 
112  auto rrIt = indexIt->second;
113  m_routeToRr.erase(indexIt);
114 
115  if (--rrIt->nRibRoutes > 0) {
116  NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
117  ',' << ribRoute.route->origin << ") needed-by " << rrIt->nRibRoutes);
118  return;
119  }
120 
121  rrIt->retryDelay = RETRY_DELAY_MIN;
122  this->withdraw(rrIt);
123 }
124 
125 void
126 Readvertise::afterDestinationAvailable()
127 {
128  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end(); ++rrIt) {
129  rrIt->retryDelay = RETRY_DELAY_MIN;
130  this->advertise(rrIt);
131  }
132 }
133 
134 void
135 Readvertise::afterDestinationUnavailable()
136 {
137  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end();) {
138  if (rrIt->nRibRoutes > 0) {
139  rrIt->retryEvt.cancel(); // stop retrying or refreshing
140  ++rrIt;
141  }
142  else {
143  rrIt = m_rrs.erase(rrIt); // assume withdraw has completed
144  }
145  }
146 }
147 
148 void
149 Readvertise::advertise(ReadvertisedRouteContainer::iterator rrIt)
150 {
151  BOOST_ASSERT(rrIt->nRibRoutes > 0);
152 
153  if (!m_destination->isAvailable()) {
154  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " destination-unavailable");
155  return;
156  }
157 
158  m_destination->advertise(*rrIt,
159  [this, rrIt] {
160  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
161  rrIt->retryDelay = RETRY_DELAY_MIN;
162  rrIt->retryEvt = scheduler::schedule(randomizeTimer(m_policy->getRefreshInterval()),
163  bind(&Readvertise::advertise, this, rrIt));
164  },
165  [this, rrIt] (const std::string& msg) {
166  NFD_LOG_DEBUG("advertise " << rrIt->prefix << " failure " << msg);
167  rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
168  rrIt->retryEvt = scheduler::schedule(randomizeTimer(rrIt->retryDelay),
169  bind(&Readvertise::advertise, this, rrIt));
170  });
171 }
172 
173 void
174 Readvertise::withdraw(ReadvertisedRouteContainer::iterator rrIt)
175 {
176  BOOST_ASSERT(rrIt->nRibRoutes == 0);
177 
178  if (!m_destination->isAvailable()) {
179  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " destination-unavailable");
180  m_rrs.erase(rrIt);
181  return;
182  }
183 
184  m_destination->withdraw(*rrIt,
185  [this, rrIt] {
186  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " success");
187  m_rrs.erase(rrIt);
188  },
189  [this, rrIt] (const std::string& msg) {
190  NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
191  rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
192  rrIt->retryEvt = scheduler::schedule(randomizeTimer(rrIt->retryDelay),
193  bind(&Readvertise::withdraw, this, rrIt));
194  });
195 }
196 
197 } // namespace rib
198 } // namespace nfd
Declares the global pseudorandom number generator (PRNG) for NFD.
represents the Routing Information Base
Definition: rib.hpp:59
ndn::util::signal::Signal< Rib, RibRouteRef > afterAddRoute
signals after a Route is added
Definition: rib.hpp:237
STL namespace.
Readvertise(Rib &rib, unique_ptr< ReadvertisePolicy > policy, unique_ptr< ReadvertiseDestination > destination)
Definition: readvertise.cpp:46
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
RibEntry::const_iterator route
Definition: rib.hpp:46
references a route
Definition: rib.hpp:43
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
static time::milliseconds randomizeTimer(time::milliseconds baseTimer)
Definition: readvertise.cpp:39
std::mt19937 & getGlobalRng()
Definition: random.cpp:32
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
EventId schedule(time::nanoseconds after, const EventCallback &event)
Schedule an event.
Definition: scheduler.cpp:48
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
ndn::util::signal::Signal< Rib, RibRouteRef > beforeRemoveRoute
signals before a route is removed
Definition: rib.hpp:241