Loading...
Searching...
No Matches
rib-entry.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2025, 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 "rib-entry.hpp"
27#include "common/logger.hpp"
28
29#include <ndn-cxx/mgmt/nfd/control-command.hpp>
30
31namespace nfd::rib {
32
33NFD_LOG_INIT(RibEntry);
34
35static bool
36compareFaceIdAndOrigin(const Route& lhs, const Route& rhs)
37{
38 return lhs.faceId == rhs.faceId && lhs.origin == rhs.origin;
39}
40
41RibEntry::RouteList::iterator
43{
44 return std::find_if(begin(), end(),
45 [&] (const auto& r) { return compareFaceIdAndOrigin(r, route); });
46}
47
48RibEntry::RouteList::const_iterator
49RibEntry::findRoute(const Route& route) const
50{
51 return std::find_if(begin(), end(),
52 [&] (const auto& r) { return compareFaceIdAndOrigin(r, route); });
53}
54
55std::pair<RibEntry::iterator, bool>
57{
58 auto it = findRoute(route);
59
60 if (it == end()) {
61 if (route.flags & ndn::nfd::ROUTE_FLAG_CAPTURE) {
62 m_nRoutesWithCaptureSet++;
63 }
64
65 m_routes.push_back(route);
66 return {std::prev(m_routes.end()), true};
67 }
68
69 return {it, false};
70}
71
72void
74{
75 eraseRoute(findRoute(route));
76}
77
78bool
79RibEntry::hasFaceId(uint64_t faceId) const
80{
81 return std::find_if(begin(), end(), [=] (const auto& r) { return r.faceId == faceId; }) != end();
82}
83
84void
85RibEntry::addChild(shared_ptr<RibEntry> child)
86{
87 BOOST_ASSERT(!child->getParent());
88 child->m_parent = shared_from_this();
89 m_children.push_back(std::move(child));
90}
91
92void
93RibEntry::removeChild(shared_ptr<RibEntry> child)
94{
95 BOOST_ASSERT(child->getParent().get() == this);
96 child->m_parent = nullptr;
97 m_children.remove(child);
98}
99
100RibEntry::RouteList::iterator
101RibEntry::eraseRoute(RouteList::iterator route)
102{
103 if (route != m_routes.end()) {
104 if (route->flags & ndn::nfd::ROUTE_FLAG_CAPTURE) {
105 m_nRoutesWithCaptureSet--;
106 }
107
108 // Cancel any scheduled event
109 NFD_LOG_TRACE("Cancelling expiration event: " << route->getExpirationEvent());
110 route->cancelExpirationEvent();
111
112 return m_routes.erase(route);
113 }
114
115 return m_routes.end();
116}
117
118void
120{
121 m_inheritedRoutes.push_back(route);
122}
123
124void
126{
127 m_inheritedRoutes.remove_if([id = route.faceId] (const auto& r) { return r.faceId == id; });
128}
129
130RibEntry::RouteList::const_iterator
132{
133 return std::find_if(m_inheritedRoutes.begin(), m_inheritedRoutes.end(),
134 [id = route.faceId] (const auto& r) { return r.faceId == id; });
135}
136
137bool
139{
140 return findInheritedRoute(route) != m_inheritedRoutes.end();
141}
142
143bool
145{
146 for (const Route& route : m_routes) {
147 if (route.faceId == faceId && (route.flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)) {
148 return true;
149 }
150 }
151
152 return false;
153}
154
155const Route*
157{
158 const Route* candidate = nullptr;
159
160 for (const Route& route : m_routes) {
161 // Matching face ID
162 if (route.faceId == faceId) {
163 // If this is the first route with this Face ID found
164 if (candidate == nullptr) {
165 candidate = &route;
166 }
167 else if (route.cost < candidate->cost) {
168 // Found a route with a lower cost
169 candidate = &route;
170 }
171 }
172 }
173
174 return candidate;
175}
176
177const Route*
179{
180 std::vector<const Route*> matches;
181
182 // Copy routes which have faceId
183 for (const Route& route : m_routes) {
184 if (route.faceId == faceId) {
185 matches.push_back(&route);
186 }
187 }
188
189 // If there are less than 2 routes, there is no second lowest
190 if (matches.size() < 2) {
191 return nullptr;
192 }
193
194 // Get second lowest cost
195 std::nth_element(matches.begin(), matches.begin() + 1, matches.end(),
196 [] (const Route* lhs, const Route* rhs) { return lhs->cost < rhs->cost; });
197
198 return matches.at(1);
199}
200
201const Route*
203{
204 const Route* candidate = nullptr;
205
206 for (const Route& route : m_routes) {
207 // Correct face ID and Child Inherit flag set
208 if (route.faceId == faceId &&
209 (route.flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT) == ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
210 {
211 // If this is the first route with this Face ID found
212 if (candidate == nullptr) {
213 candidate = &route;
214 }
215 else if (route.cost < candidate->cost) {
216 // Found a route with a lower cost
217 candidate = &route;
218 }
219 }
220 }
221
222 return candidate;
223}
224
225ndn::PrefixAnnouncement
226RibEntry::getPrefixAnnouncement(time::milliseconds minExpiration,
227 time::milliseconds maxExpiration) const
228{
229 const Route* bestAnnRoute = nullptr;
230 auto entryExpiry = time::steady_clock::time_point::min();
231
232 for (const Route& route : *this) {
233 if (route.expires) {
234 entryExpiry = std::max(entryExpiry, *route.expires);
235 if (route.announcement) {
236 if (bestAnnRoute == nullptr || *route.expires > *bestAnnRoute->expires) {
237 bestAnnRoute = &route;
238 }
239 }
240 }
241 else {
242 entryExpiry = time::steady_clock::time_point::max();
243 }
244 }
245
246 if (bestAnnRoute != nullptr) {
247 return *bestAnnRoute->announcement;
248 }
249
250 ndn::PrefixAnnouncement ann;
251 ann.setAnnouncedName(m_name);
252 ann.setExpiration(std::clamp(
253 time::duration_cast<time::milliseconds>(entryExpiry - time::steady_clock::now()),
254 minExpiration, maxExpiration));
255 return ann;
256}
257
258std::ostream&
259operator<<(std::ostream& os, const RibEntry& entry)
260{
261 os << "RibEntry {\n"
262 << " Name: " << entry.getName() << "\n";
263 for (const Route& route : entry) {
264 os << " " << route << "\n";
265 }
266 return os << "}";
267}
268
269} // namespace nfd::rib
Represents a RIB entry, which contains one or more Routes with the same prefix.
Definition rib-entry.hpp:39
RouteList::const_iterator findInheritedRoute(const Route &route) const
Finds an inherited route with a matching face ID.
const Route * getRouteWithLowestCostByFaceId(uint64_t faceId) const
Returns the route with the lowest cost that has the passed face ID.
iterator findRoute(const Route &route)
Definition rib-entry.cpp:42
void addInheritedRoute(const Route &route)
void removeInheritedRoute(const Route &route)
std::pair< RibEntry::iterator, bool > insertRoute(const Route &route)
Inserts a new route into the entry's route list.
Definition rib-entry.cpp:56
const_iterator end() const noexcept
void eraseRoute(const Route &route)
Erases a Route with the same FaceId and origin.
Definition rib-entry.cpp:73
const Route * getRouteWithLowestCostAndChildInheritByFaceId(uint64_t faceId) const
Returns the route with the lowest cost that has the passed face ID and its child inherit flag set.
void addChild(shared_ptr< RibEntry > child)
Definition rib-entry.cpp:85
ndn::PrefixAnnouncement getPrefixAnnouncement(time::milliseconds minExpiration=15_s, time::milliseconds maxExpiration=1_h) const
Retrieve a prefix announcement suitable for readvertising this route.
void removeChild(shared_ptr< RibEntry > child)
Definition rib-entry.cpp:93
const Route * getRouteWithSecondLowestCostByFaceId(uint64_t faceId) const
bool hasFaceId(uint64_t faceId) const
Definition rib-entry.cpp:79
const_iterator begin() const noexcept
bool hasChildInheritOnFaceId(uint64_t faceId) const
Determines if the entry has an inherited route with the passed face ID and its child inherit flag set...
const Name & getName() const noexcept
Definition rib-entry.hpp:46
bool hasInheritedRoute(const Route &route) const
Determines if the entry has an inherited route with a matching face ID.
Represents a route for a name prefix.
Definition route.hpp:44
ndn::nfd::RouteOrigin origin
Definition route.hpp:97
uint64_t cost
Definition route.hpp:98
std::underlying_type_t< ndn::nfd::RouteFlags > flags
Definition route.hpp:99
std::optional< time::steady_clock::time_point > expires
Definition route.hpp:100
std::optional< ndn::PrefixAnnouncement > announcement
The prefix announcement that caused the creation of this route.
Definition route.hpp:106
uint64_t faceId
Definition route.hpp:96
#define NFD_LOG_INIT(name)
Definition logger.hpp:31
#define NFD_LOG_TRACE
Definition logger.hpp:37
std::ostream & operator<<(std::ostream &os, const FibUpdate &update)
static bool compareFaceIdAndOrigin(const Route &lhs, const Route &rhs)
Definition rib-entry.cpp:36