blob: f7eb4cdaca33991a72c284cc4ee05c29e4c268df [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/*
Davide Pesaventob7bfcb92022-05-22 23:55:23 -04003 * Copyright (c) 2014-2022, 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"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040027#include "common/global.hpp"
28#include "common/logger.hpp"
Davide Pesaventob8bd5ee2019-02-03 22:53:40 -050029
30#include <ndn-cxx/util/random.hpp>
Junxiao Shi89c0ea02017-03-06 19:52:05 +000031
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040032namespace nfd::rib {
Junxiao Shi89c0ea02017-03-06 19:52:05 +000033
Davide Pesaventoa3148082018-04-12 18:21:54 -040034NFD_LOG_INIT(Readvertise);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000035
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040036constexpr time::milliseconds RETRY_DELAY_MIN = 50_s;
37constexpr time::milliseconds RETRY_DELAY_MAX = 1_h;
Junxiao Shi89c0ea02017-03-06 19:52:05 +000038
39static time::milliseconds
40randomizeTimer(time::milliseconds baseTimer)
41{
Davide Pesaventob8bd5ee2019-02-03 22:53:40 -050042 std::uniform_int_distribution<> dist(-5, 5);
43 auto newTime = baseTimer + time::milliseconds(dist(ndn::random::getRandomNumberEngine()));
Davide Pesaventoe4b22382018-06-10 14:37:24 -040044 return std::max(newTime, 0_ms);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000045}
46
Davide Pesavento0a71dd32019-03-17 20:36:18 -040047Readvertise::Readvertise(Rib& rib,
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040048 unique_ptr<ReadvertisePolicy> policy,
Junxiao Shi89c0ea02017-03-06 19:52:05 +000049 unique_ptr<ReadvertiseDestination> destination)
Davide Pesavento0a71dd32019-03-17 20:36:18 -040050 : m_policy(std::move(policy))
Junxiao Shi89c0ea02017-03-06 19:52:05 +000051 , m_destination(std::move(destination))
52{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040053 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); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +000055
56 m_destination->afterAvailabilityChange.connect([this] (bool isAvailable) {
57 if (isAvailable) {
58 this->afterDestinationAvailable();
59 }
60 else {
61 this->afterDestinationUnavailable();
62 }
63 });
64}
65
66void
67Readvertise::afterAddRoute(const RibRouteRef& ribRoute)
68{
Davide Pesaventob7bfcb92022-05-22 23:55:23 -040069 std::optional<ReadvertiseAction> action = m_policy->handleNewRoute(ribRoute);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000070 if (!action) {
71 NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
72 ',' << ribRoute.route->origin << ") not-readvertising");
73 return;
74 }
75
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040076 auto [rrIt, isNewRr] = m_rrs.emplace(action->prefix);
77 if (!isNewRr && rrIt->signer != action->signer) {
Junxiao Shi89c0ea02017-03-06 19:52:05 +000078 NFD_LOG_WARN("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040079 ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
Junxiao Shi89c0ea02017-03-06 19:52:05 +000080 " old-signer " << rrIt->signer << " new-signer " << action->signer);
81 }
82 rrIt->signer = action->signer;
83
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040084 bool isNewInMap = m_routeToRr.try_emplace(ribRoute, rrIt).second;
85 BOOST_VERIFY(isNewInMap);
Junxiao Shi89c0ea02017-03-06 19:52:05 +000086
87 if (rrIt->nRibRoutes++ > 0) {
88 NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
89 ',' << ribRoute.route->origin << ") already-readvertised-as " << action->prefix);
90 return;
91 }
92
93 NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
94 ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
95 " signer " << action->signer);
96 rrIt->retryDelay = RETRY_DELAY_MIN;
97 this->advertise(rrIt);
98}
99
100void
101Readvertise::beforeRemoveRoute(const RibRouteRef& ribRoute)
102{
103 auto indexIt = m_routeToRr.find(ribRoute);
104 if (indexIt == m_routeToRr.end()) {
105 NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
106 ',' << ribRoute.route->origin << ") not-readvertised");
107 return;
108 }
109
110 auto rrIt = indexIt->second;
111 m_routeToRr.erase(indexIt);
112
113 if (--rrIt->nRibRoutes > 0) {
114 NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
115 ',' << ribRoute.route->origin << ") needed-by " << rrIt->nRibRoutes);
116 return;
117 }
118
119 rrIt->retryDelay = RETRY_DELAY_MIN;
120 this->withdraw(rrIt);
121}
122
123void
124Readvertise::afterDestinationAvailable()
125{
126 for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end(); ++rrIt) {
127 rrIt->retryDelay = RETRY_DELAY_MIN;
128 this->advertise(rrIt);
129 }
130}
131
132void
133Readvertise::afterDestinationUnavailable()
134{
135 for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end();) {
136 if (rrIt->nRibRoutes > 0) {
137 rrIt->retryEvt.cancel(); // stop retrying or refreshing
138 ++rrIt;
139 }
140 else {
141 rrIt = m_rrs.erase(rrIt); // assume withdraw has completed
142 }
143 }
144}
145
146void
147Readvertise::advertise(ReadvertisedRouteContainer::iterator rrIt)
148{
149 BOOST_ASSERT(rrIt->nRibRoutes > 0);
150
151 if (!m_destination->isAvailable()) {
152 NFD_LOG_DEBUG("advertise " << rrIt->prefix << " destination-unavailable");
153 return;
154 }
155
156 m_destination->advertise(*rrIt,
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400157 [=] {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000158 NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
159 rrIt->retryDelay = RETRY_DELAY_MIN;
Davide Pesavento0a71dd32019-03-17 20:36:18 -0400160 rrIt->retryEvt = getScheduler().schedule(randomizeTimer(m_policy->getRefreshInterval()),
161 [=] { advertise(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000162 },
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400163 [=] (const std::string& msg) {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000164 NFD_LOG_DEBUG("advertise " << rrIt->prefix << " failure " << msg);
165 rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
Davide Pesavento0a71dd32019-03-17 20:36:18 -0400166 rrIt->retryEvt = getScheduler().schedule(randomizeTimer(rrIt->retryDelay),
167 [=] { advertise(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000168 });
169}
170
171void
172Readvertise::withdraw(ReadvertisedRouteContainer::iterator rrIt)
173{
174 BOOST_ASSERT(rrIt->nRibRoutes == 0);
175
176 if (!m_destination->isAvailable()) {
177 NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " destination-unavailable");
178 m_rrs.erase(rrIt);
179 return;
180 }
181
182 m_destination->withdraw(*rrIt,
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400183 [=] {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000184 NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " success");
185 m_rrs.erase(rrIt);
186 },
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400187 [=] (const std::string& msg) {
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000188 NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
189 rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
Davide Pesavento0a71dd32019-03-17 20:36:18 -0400190 rrIt->retryEvt = getScheduler().schedule(randomizeTimer(rrIt->retryDelay),
191 [=] { withdraw(rrIt); });
Junxiao Shi89c0ea02017-03-06 19:52:05 +0000192 });
193}
194
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400195} // namespace nfd::rib