blob: 7a467ef452b24789d45ce9158a0eec3228d8dfc0 [file] [log] [blame]
Junxiao Shi89c0ea02017-03-06 19:52:05 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento87fc0f82018-04-11 23:43:51 -04002/*
3 * Copyright (c) 2014-2018, Regents of the University of California,
Junxiao Shi89c0ea02017-03-06 19:52:05 +00004 * 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
30namespace nfd {
31namespace rib {
32
Davide Pesaventoa3148082018-04-12 18:21:54 -040033NFD_LOG_INIT(Readvertise);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000034
Davide Pesaventoe4b22382018-06-10 14:37:24 -040035const time::milliseconds Readvertise::RETRY_DELAY_MIN = 50_s;
36const time::milliseconds Readvertise::RETRY_DELAY_MAX = 3600_s;
Junxiao Shi89c0ea02017-03-06 19:52:05 +000037
38static time::milliseconds
39randomizeTimer(time::milliseconds baseTimer)
40{
41 std::uniform_int_distribution<uint64_t> dist(-5, 5);
42 time::milliseconds newTime = baseTimer + time::milliseconds(dist(getGlobalRng()));
Davide Pesaventoe4b22382018-06-10 14:37:24 -040043 return std::max(newTime, 0_ms);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000044}
45
46Readvertise::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{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040051 m_addRouteConn = rib.afterAddRoute.connect([this] (const auto& r) { this->afterAddRoute(r); });
52 m_removeRouteConn = rib.beforeRemoveRoute.connect([this] (const auto& r) { this->beforeRemoveRoute(r); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +000053
54 m_destination->afterAvailabilityChange.connect([this] (bool isAvailable) {
55 if (isAvailable) {
56 this->afterDestinationAvailable();
57 }
58 else {
59 this->afterDestinationUnavailable();
60 }
61 });
62}
63
64void
65Readvertise::afterAddRoute(const RibRouteRef& ribRoute)
66{
Davide Pesavento87fc0f82018-04-11 23:43:51 -040067 optional<ReadvertiseAction> action = m_policy->handleNewRoute(ribRoute);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000068 if (!action) {
69 NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
70 ',' << ribRoute.route->origin << ") not-readvertising");
71 return;
72 }
73
74 ReadvertisedRouteContainer::iterator rrIt;
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
102void
103Readvertise::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
125void
126Readvertise::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
134void
135Readvertise::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
148void
149Readvertise::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,
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400159 [=] {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000160 NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
161 rrIt->retryDelay = RETRY_DELAY_MIN;
162 rrIt->retryEvt = scheduler::schedule(randomizeTimer(m_policy->getRefreshInterval()),
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400163 [=] { advertise(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000164 },
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400165 [=] (const std::string& msg) {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000166 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),
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400169 [=] { advertise(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000170 });
171}
172
173void
174Readvertise::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,
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400185 [=] {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000186 NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " success");
187 m_rrs.erase(rrIt);
188 },
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400189 [=] (const std::string& msg) {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000190 NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
191 rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400192 rrIt->retryEvt = scheduler::schedule(randomizeTimer(rrIt->retryDelay), [=] { withdraw(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000193 });
194}
195
196} // namespace rib
197} // namespace nfd