blob: 1710aff5dbc0fec4c21161faf554b5aba2006f79 [file] [log] [blame]
Vince12e49462014-06-09 13:29:32 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa3148082018-04-12 18:21:54 -04002/*
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -04003 * Copyright (c) 2014-2022, Regents of the University of California,
Alexander Afanasyev7c10b3b2015-01-20 12:24:27 -08004 * 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.
Vince12e49462014-06-09 13:29:32 -050010 *
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 "rib-entry.hpp"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040027#include "common/logger.hpp"
Vince Lehman281ded72014-08-21 12:17:08 -050028
Junxiao Shi25c6ce42016-09-09 13:49:59 +000029#include <ndn-cxx/mgmt/nfd/control-command.hpp>
Vince12e49462014-06-09 13:29:32 -050030
31namespace nfd {
32namespace rib {
33
Davide Pesaventoa3148082018-04-12 18:21:54 -040034NFD_LOG_INIT(RibEntry);
35
Davide Pesavento412c9822021-07-02 00:21:05 -040036static bool
37compareFaceIdAndOrigin(const Route& lhs, const Route& rhs)
38{
39 return lhs.faceId == rhs.faceId && lhs.origin == rhs.origin;
40}
41
Vince Lehman218be0a2015-01-15 17:25:20 -060042RibEntry::RouteList::iterator
43RibEntry::findRoute(const Route& route)
Vince12e49462014-06-09 13:29:32 -050044{
Davide Pesavento412c9822021-07-02 00:21:05 -040045 return std::find_if(begin(), end(),
46 [&] (const auto& r) { return compareFaceIdAndOrigin(r, route); });
Vince12e49462014-06-09 13:29:32 -050047}
48
Vince Lehman76c751c2014-11-18 17:36:38 -060049RibEntry::RouteList::const_iterator
50RibEntry::findRoute(const Route& route) const
51{
Davide Pesavento412c9822021-07-02 00:21:05 -040052 return std::find_if(begin(), end(),
53 [&] (const auto& r) { return compareFaceIdAndOrigin(r, route); });
Vince Lehman76c751c2014-11-18 17:36:38 -060054}
55
Nick Gordon89c4cca2016-11-02 15:42:32 +000056std::pair<RibEntry::iterator, bool>
Vince Lehman218be0a2015-01-15 17:25:20 -060057RibEntry::insertRoute(const Route& route)
Vince12e49462014-06-09 13:29:32 -050058{
Davide Pesavento412c9822021-07-02 00:21:05 -040059 auto it = findRoute(route);
Vince12e49462014-06-09 13:29:32 -050060
Vince Lehman76c751c2014-11-18 17:36:38 -060061 if (it == end()) {
62 if (route.flags & ndn::nfd::ROUTE_FLAG_CAPTURE) {
63 m_nRoutesWithCaptureSet++;
64 }
Vince Lehman4387e782014-06-19 16:57:45 -050065
Vince Lehman76c751c2014-11-18 17:36:38 -060066 m_routes.push_back(route);
Davide Pesaventoe4b22382018-06-10 14:37:24 -040067 return {std::prev(m_routes.end()), true};
68 }
Vince Lehman76c751c2014-11-18 17:36:38 -060069
Davide Pesaventoe4b22382018-06-10 14:37:24 -040070 return {it, false};
Vince12e49462014-06-09 13:29:32 -050071}
72
Vince Lehman281ded72014-08-21 12:17:08 -050073void
Vince Lehman218be0a2015-01-15 17:25:20 -060074RibEntry::eraseRoute(const Route& route)
Vince12e49462014-06-09 13:29:32 -050075{
Davide Pesavento412c9822021-07-02 00:21:05 -040076 auto it = findRoute(route);
Vince Lehman218be0a2015-01-15 17:25:20 -060077 eraseRoute(it);
Vince12e49462014-06-09 13:29:32 -050078}
79
80bool
Vince Lehman218be0a2015-01-15 17:25:20 -060081RibEntry::hasRoute(const Route& route)
Vince Lehman4387e782014-06-19 16:57:45 -050082{
Davide Pesavento412c9822021-07-02 00:21:05 -040083 auto it = findRoute(route);
Vince Lehman218be0a2015-01-15 17:25:20 -060084 return it != end();
Vince Lehman4387e782014-06-19 16:57:45 -050085}
86
87bool
Davide Pesavento412c9822021-07-02 00:21:05 -040088RibEntry::hasFaceId(uint64_t faceId) const
Vince12e49462014-06-09 13:29:32 -050089{
Davide Pesavento412c9822021-07-02 00:21:05 -040090 auto it = std::find_if(begin(), end(), [faceId] (const auto& r) { return r.faceId == faceId; });
Vince Lehman218be0a2015-01-15 17:25:20 -060091 return it != end();
Vince12e49462014-06-09 13:29:32 -050092}
93
Vince Lehman76c751c2014-11-18 17:36:38 -060094size_t
95RibEntry::getNRoutes() const
96{
97 return m_routes.size();
98}
99
Vince12e49462014-06-09 13:29:32 -0500100void
101RibEntry::addChild(shared_ptr<RibEntry> child)
102{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400103 BOOST_ASSERT(!child->getParent());
Vince12e49462014-06-09 13:29:32 -0500104 child->setParent(this->shared_from_this());
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400105 m_children.push_back(std::move(child));
Vince12e49462014-06-09 13:29:32 -0500106}
107
108void
109RibEntry::removeChild(shared_ptr<RibEntry> child)
110{
111 BOOST_ASSERT(child->getParent().get() == this);
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400112 child->setParent(nullptr);
Vince12e49462014-06-09 13:29:32 -0500113 m_children.remove(child);
114}
115
Vince Lehman218be0a2015-01-15 17:25:20 -0600116RibEntry::RouteList::iterator
117RibEntry::eraseRoute(RouteList::iterator route)
Vince12e49462014-06-09 13:29:32 -0500118{
Vince Lehman76c751c2014-11-18 17:36:38 -0600119 if (route != m_routes.end()) {
120 if (route->flags & ndn::nfd::ROUTE_FLAG_CAPTURE) {
121 m_nRoutesWithCaptureSet--;
Vince Lehman4387e782014-06-19 16:57:45 -0500122 }
123
Vince Lehman76c751c2014-11-18 17:36:38 -0600124 // Cancel any scheduled event
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400125 NFD_LOG_TRACE("Cancelling expiration event: " << route->getExpirationEvent());
126 route->cancelExpirationEvent();
Vince Lehman76c751c2014-11-18 17:36:38 -0600127
128 return m_routes.erase(route);
129 }
130
Vince Lehman218be0a2015-01-15 17:25:20 -0600131 return m_routes.end();
Vince Lehman4387e782014-06-19 16:57:45 -0500132}
133
134void
Vince Lehman218be0a2015-01-15 17:25:20 -0600135RibEntry::addInheritedRoute(const Route& route)
Vince Lehman4387e782014-06-19 16:57:45 -0500136{
Vince Lehman218be0a2015-01-15 17:25:20 -0600137 m_inheritedRoutes.push_back(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500138}
139
140void
Vince Lehman218be0a2015-01-15 17:25:20 -0600141RibEntry::removeInheritedRoute(const Route& route)
Vince Lehman4387e782014-06-19 16:57:45 -0500142{
Davide Pesavento412c9822021-07-02 00:21:05 -0400143 m_inheritedRoutes.remove_if([id = route.faceId] (const auto& r) { return r.faceId == id; });
Vince Lehman4387e782014-06-19 16:57:45 -0500144}
145
Vince Lehman76c751c2014-11-18 17:36:38 -0600146RibEntry::RouteList::const_iterator
147RibEntry::findInheritedRoute(const Route& route) const
Vince Lehman4387e782014-06-19 16:57:45 -0500148{
Vince Lehman218be0a2015-01-15 17:25:20 -0600149 return std::find_if(m_inheritedRoutes.begin(), m_inheritedRoutes.end(),
Davide Pesavento412c9822021-07-02 00:21:05 -0400150 [id = route.faceId] (const auto& r) { return r.faceId == id; });
Vince Lehman4387e782014-06-19 16:57:45 -0500151}
152
153bool
Vince Lehman76c751c2014-11-18 17:36:38 -0600154RibEntry::hasInheritedRoute(const Route& route) const
Vince Lehman4387e782014-06-19 16:57:45 -0500155{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400156 return findInheritedRoute(route) != m_inheritedRoutes.end();
Vince Lehman4387e782014-06-19 16:57:45 -0500157}
158
159bool
160RibEntry::hasCapture() const
161{
Vince Lehman218be0a2015-01-15 17:25:20 -0600162 return m_nRoutesWithCaptureSet > 0;
Vince Lehman4387e782014-06-19 16:57:45 -0500163}
164
165bool
166RibEntry::hasChildInheritOnFaceId(uint64_t faceId) const
167{
Vince Lehman76c751c2014-11-18 17:36:38 -0600168 for (const Route& route : m_routes) {
169 if (route.faceId == faceId && (route.flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)) {
170 return true;
Vince Lehman4387e782014-06-19 16:57:45 -0500171 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600172 }
Vince Lehman4387e782014-06-19 16:57:45 -0500173
174 return false;
175}
176
Vince Lehman9dcfc402015-03-26 03:18:54 -0500177const Route*
Vince Lehman76c751c2014-11-18 17:36:38 -0600178RibEntry::getRouteWithLowestCostByFaceId(uint64_t faceId) const
Vince Lehman4387e782014-06-19 16:57:45 -0500179{
Vince Lehman9dcfc402015-03-26 03:18:54 -0500180 const Route* candidate = nullptr;
Vince Lehman4387e782014-06-19 16:57:45 -0500181
Vince Lehman76c751c2014-11-18 17:36:38 -0600182 for (const Route& route : m_routes) {
183 // Matching face ID
184 if (route.faceId == faceId) {
185 // If this is the first route with this Face ID found
186 if (candidate == nullptr) {
Vince Lehman9dcfc402015-03-26 03:18:54 -0500187 candidate = &route;
Vince Lehman76c751c2014-11-18 17:36:38 -0600188 }
189 else if (route.cost < candidate->cost) {
190 // Found a route with a lower cost
Vince Lehman9dcfc402015-03-26 03:18:54 -0500191 candidate = &route;
Vince Lehman76c751c2014-11-18 17:36:38 -0600192 }
Vince Lehman4387e782014-06-19 16:57:45 -0500193 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600194 }
Vince Lehman4387e782014-06-19 16:57:45 -0500195
Vince Lehman218be0a2015-01-15 17:25:20 -0600196 return candidate;
Vince Lehman4387e782014-06-19 16:57:45 -0500197}
198
Vince Lehman76c751c2014-11-18 17:36:38 -0600199const Route*
200RibEntry::getRouteWithSecondLowestCostByFaceId(uint64_t faceId) const
201{
Vince Lehman4310d502016-03-04 11:58:59 -0600202 std::vector<const Route*> matches;
Vince Lehman76c751c2014-11-18 17:36:38 -0600203
204 // Copy routes which have faceId
Vince Lehman4310d502016-03-04 11:58:59 -0600205 for (const Route& route : m_routes) {
206 if (route.faceId == faceId) {
207 matches.push_back(&route);
208 }
209 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600210
Vince Lehman4310d502016-03-04 11:58:59 -0600211 // If there are less than 2 routes, there is no second lowest
Vince Lehman76c751c2014-11-18 17:36:38 -0600212 if (matches.size() < 2) {
213 return nullptr;
214 }
215
216 // Get second lowest cost
217 std::nth_element(matches.begin(), matches.begin() + 1, matches.end(),
Vince Lehman4310d502016-03-04 11:58:59 -0600218 [] (const Route* lhs, const Route* rhs) { return lhs->cost < rhs->cost; });
Vince Lehman76c751c2014-11-18 17:36:38 -0600219
Vince Lehman4310d502016-03-04 11:58:59 -0600220 return matches.at(1);
Vince Lehman76c751c2014-11-18 17:36:38 -0600221}
222
Vince Lehman9dcfc402015-03-26 03:18:54 -0500223const Route*
Vince Lehman76c751c2014-11-18 17:36:38 -0600224RibEntry::getRouteWithLowestCostAndChildInheritByFaceId(uint64_t faceId) const
Vince Lehman4387e782014-06-19 16:57:45 -0500225{
Vince Lehman9dcfc402015-03-26 03:18:54 -0500226 const Route* candidate = nullptr;
Vince Lehman4387e782014-06-19 16:57:45 -0500227
Vince Lehman76c751c2014-11-18 17:36:38 -0600228 for (const Route& route : m_routes) {
229 // Correct face ID and Child Inherit flag set
230 if (route.faceId == faceId &&
231 (route.flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT) == ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
Vince Lehman4387e782014-06-19 16:57:45 -0500232 {
Vince Lehman76c751c2014-11-18 17:36:38 -0600233 // If this is the first route with this Face ID found
234 if (candidate == nullptr) {
Vince Lehman9dcfc402015-03-26 03:18:54 -0500235 candidate = &route;
Vince Lehman76c751c2014-11-18 17:36:38 -0600236 }
237 else if (route.cost < candidate->cost) {
238 // Found a route with a lower cost
Vince Lehman9dcfc402015-03-26 03:18:54 -0500239 candidate = &route;
Vince Lehman76c751c2014-11-18 17:36:38 -0600240 }
Vince Lehman4387e782014-06-19 16:57:45 -0500241 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600242 }
Vince Lehman4387e782014-06-19 16:57:45 -0500243
Vince Lehman218be0a2015-01-15 17:25:20 -0600244 return candidate;
Vince12e49462014-06-09 13:29:32 -0500245}
246
Junxiao Shid47cd632018-09-11 03:10:00 +0000247ndn::PrefixAnnouncement
248RibEntry::getPrefixAnnouncement(time::milliseconds minExpiration,
249 time::milliseconds maxExpiration) const
250{
251 const Route* bestAnnRoute = nullptr;
Davide Pesavento412c9822021-07-02 00:21:05 -0400252 auto entryExpiry = time::steady_clock::time_point::min();
Junxiao Shid47cd632018-09-11 03:10:00 +0000253
254 for (const Route& route : *this) {
255 if (route.expires) {
256 entryExpiry = std::max(entryExpiry, *route.expires);
257 if (route.announcement) {
258 if (bestAnnRoute == nullptr || *route.expires > *bestAnnRoute->expires) {
259 bestAnnRoute = &route;
260 }
261 }
262 }
263 else {
Davide Pesavento412c9822021-07-02 00:21:05 -0400264 entryExpiry = time::steady_clock::time_point::max();
Junxiao Shid47cd632018-09-11 03:10:00 +0000265 }
266 }
267
268 if (bestAnnRoute != nullptr) {
269 return *bestAnnRoute->announcement;
270 }
271
272 ndn::PrefixAnnouncement ann;
273 ann.setAnnouncedName(m_name);
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400274 ann.setExpiration(std::clamp(
Junxiao Shid47cd632018-09-11 03:10:00 +0000275 time::duration_cast<time::milliseconds>(entryExpiry - time::steady_clock::now()),
276 minExpiration, maxExpiration));
277 return ann;
278}
279
Vince12e49462014-06-09 13:29:32 -0500280std::ostream&
Vince12e49462014-06-09 13:29:32 -0500281operator<<(std::ostream& os, const RibEntry& entry)
282{
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400283 os << "RibEntry {\n"
284 << " Name: " << entry.getName() << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600285 for (const Route& route : entry) {
Junxiao Shi3f21e582017-05-29 15:26:32 +0000286 os << " " << route << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600287 }
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400288 return os << "}";
Vince12e49462014-06-09 13:29:32 -0500289}
290
291} // namespace rib
292} // namespace nfd