blob: d6b125b33cca26b18efc24053d32a6f217f7804b [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa3148082018-04-12 18:21:54 -04002/*
3 * Copyright (c) 2014-2018, 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.
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070010 *
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/>.
Vince12e49462014-06-09 13:29:32 -050024 */
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070025
26#include "rib.hpp"
Vince Lehman76c751c2014-11-18 17:36:38 -060027#include "fib-updater.hpp"
Vince Lehman281ded72014-08-21 12:17:08 -050028#include "core/logger.hpp"
29
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070030namespace nfd {
31namespace rib {
32
Davide Pesaventoa3148082018-04-12 18:21:54 -040033NFD_LOG_INIT(Rib);
34
Junxiao Shi89c0ea02017-03-06 19:52:05 +000035bool
36operator<(const RibRouteRef& lhs, const RibRouteRef& rhs)
37{
38 return std::tie(lhs.entry->getName(), lhs.route->faceId, lhs.route->origin) <
39 std::tie(rhs.entry->getName(), rhs.route->faceId, rhs.route->origin);
40}
41
Vince Lehman4387e782014-06-19 16:57:45 -050042static inline bool
Vince Lehman218be0a2015-01-15 17:25:20 -060043sortRoutes(const Route& lhs, const Route& rhs)
Vince Lehman4387e782014-06-19 16:57:45 -050044{
Vince Lehman218be0a2015-01-15 17:25:20 -060045 return lhs.faceId < rhs.faceId;
Vince Lehman4387e782014-06-19 16:57:45 -050046}
47
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070048Rib::Rib()
Vince12e49462014-06-09 13:29:32 -050049 : m_nItems(0)
Vince Lehman76c751c2014-11-18 17:36:38 -060050 , m_isUpdateInProgress(false)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070051{
52}
53
Davide Pesaventoa3148082018-04-12 18:21:54 -040054Rib::~Rib() = default;
Vince Lehman76c751c2014-11-18 17:36:38 -060055
56void
57Rib::setFibUpdater(FibUpdater* updater)
58{
59 m_fibUpdater = updater;
60}
61
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070062Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050063Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070064{
Vince12e49462014-06-09 13:29:32 -050065 return m_rib.find(prefix);
66}
67
Vince Lehman218be0a2015-01-15 17:25:20 -060068Route*
69Rib::find(const Name& prefix, const Route& route) const
Vince12e49462014-06-09 13:29:32 -050070{
71 RibTable::const_iterator ribIt = m_rib.find(prefix);
72
73 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060074 if (ribIt != m_rib.end()) {
75 shared_ptr<RibEntry> entry = ribIt->second;
Vince12e49462014-06-09 13:29:32 -050076
Vince Lehman76c751c2014-11-18 17:36:38 -060077 RibEntry::iterator routeIt = entry->findRoute(route);
Vince12e49462014-06-09 13:29:32 -050078
Vince Lehman76c751c2014-11-18 17:36:38 -060079 if (routeIt != entry->end()) {
80 return &((*routeIt));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070081 }
Vince Lehman76c751c2014-11-18 17:36:38 -060082 }
Vince Lehman218be0a2015-01-15 17:25:20 -060083
84 return nullptr;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070085}
86
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070087void
Vince Lehman218be0a2015-01-15 17:25:20 -060088Rib::insert(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070089{
Vince12e49462014-06-09 13:29:32 -050090 RibTable::iterator ribIt = m_rib.find(prefix);
91
92 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060093 if (ribIt != m_rib.end()) {
94 shared_ptr<RibEntry> entry(ribIt->second);
Vince12e49462014-06-09 13:29:32 -050095
Nick Gordon89c4cca2016-11-02 15:42:32 +000096 RibEntry::iterator entryIt;
97 bool didInsert = false;
98 std::tie(entryIt, didInsert) = entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -050099
Nick Gordon89c4cca2016-11-02 15:42:32 +0000100 if (didInsert) {
101 // The route was new and we successfully inserted it.
Vince Lehman76c751c2014-11-18 17:36:38 -0600102 m_nItems++;
Vince12e49462014-06-09 13:29:32 -0500103
Nick Gordon89c4cca2016-11-02 15:42:32 +0000104 afterAddRoute(RibRouteRef{entry, entryIt});
105
Vince12e49462014-06-09 13:29:32 -0500106 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600107 m_faceMap[route.faceId].push_back(entry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700108 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600109 else {
110 // Route exists, update fields
111 // First cancel old scheduled event, if any, then set the EventId to new one
Nick Gordon89c4cca2016-11-02 15:42:32 +0000112 if (static_cast<bool>(entryIt->getExpirationEvent())) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600113 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
Nick Gordon89c4cca2016-11-02 15:42:32 +0000114 << (*entryIt));
115 scheduler::cancel(entryIt->getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600116 }
117
118 // No checks are required here as the iterator needs to be updated in all cases.
Nick Gordon89c4cca2016-11-02 15:42:32 +0000119 entryIt->setExpirationEvent(route.getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600120
Nick Gordon89c4cca2016-11-02 15:42:32 +0000121 entryIt->flags = route.flags;
122 entryIt->cost = route.cost;
123 entryIt->expires = route.expires;
Vince Lehman76c751c2014-11-18 17:36:38 -0600124 }
125 }
126 else {
127 // New name prefix
Nick Gordon89c4cca2016-11-02 15:42:32 +0000128 shared_ptr<RibEntry> entry = make_shared<RibEntry>();
Vince Lehman76c751c2014-11-18 17:36:38 -0600129
130 m_rib[prefix] = entry;
131 m_nItems++;
132
133 entry->setName(prefix);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000134 RibEntry::iterator routeIt = entry->insertRoute(route).first;
Vince Lehman76c751c2014-11-18 17:36:38 -0600135
136 // Find prefix's parent
137 shared_ptr<RibEntry> parent = findParent(prefix);
138
139 // Add self to parent's children
140 if (parent != nullptr) {
141 parent->addChild(entry);
142 }
143
144 RibEntryList children = findDescendants(prefix);
145
146 for (const auto& child : children) {
147 if (child->getParent() == parent) {
148 // Remove child from parent and inherit parent's child
149 if (parent != nullptr) {
150 parent->removeChild(child);
151 }
152
153 entry->addChild(child);
154 }
155 }
156
157 // Register with face lookup table
158 m_faceMap[route.faceId].push_back(entry);
159
160 // do something after inserting an entry
161 afterInsertEntry(prefix);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000162 afterAddRoute(RibRouteRef{entry, routeIt});
Vince Lehman76c751c2014-11-18 17:36:38 -0600163 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700164}
165
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700166void
Vince Lehman218be0a2015-01-15 17:25:20 -0600167Rib::erase(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700168{
Vince12e49462014-06-09 13:29:32 -0500169 RibTable::iterator ribIt = m_rib.find(prefix);
170
171 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -0600172 if (ribIt != m_rib.end()) {
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000173 shared_ptr<RibEntry> entry = ribIt->second;
Vince Lehman76c751c2014-11-18 17:36:38 -0600174 RibEntry::iterator routeIt = entry->findRoute(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500175
Vince Lehman76c751c2014-11-18 17:36:38 -0600176 if (routeIt != entry->end()) {
Nick Gordon89c4cca2016-11-02 15:42:32 +0000177 beforeRemoveRoute(RibRouteRef{entry, routeIt});
178
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000179 auto faceId = route.faceId;
Vince Lehman76c751c2014-11-18 17:36:38 -0600180 entry->eraseRoute(routeIt);
181 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500182
Vince Lehman76c751c2014-11-18 17:36:38 -0600183 // If this RibEntry no longer has this faceId, unregister from face lookup table
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000184 if (!entry->hasFaceId(faceId)) {
185 m_faceMap[faceId].remove(entry);
Vince Lehman76c751c2014-11-18 17:36:38 -0600186 }
Syed Obaid3313a372014-07-01 01:31:33 -0500187
Vince Lehman76c751c2014-11-18 17:36:38 -0600188 // If a RibEntry's route list is empty, remove it from the tree
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000189 if (entry->getRoutes().empty()) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600190 eraseEntry(ribIt);
191 }
Vince12e49462014-06-09 13:29:32 -0500192 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600193 }
Vince12e49462014-06-09 13:29:32 -0500194}
195
196void
Vince Lehman76c751c2014-11-18 17:36:38 -0600197Rib::onRouteExpiration(const Name& prefix, const Route& route)
Vince12e49462014-06-09 13:29:32 -0500198{
Vince Lehman76c751c2014-11-18 17:36:38 -0600199 NFD_LOG_DEBUG(route << " for " << prefix << " has expired");
Vince12e49462014-06-09 13:29:32 -0500200
Vince Lehman76c751c2014-11-18 17:36:38 -0600201 RibUpdate update;
202 update.setAction(RibUpdate::UNREGISTER)
203 .setName(prefix)
204 .setRoute(route);
Vince12e49462014-06-09 13:29:32 -0500205
Vince Lehman76c751c2014-11-18 17:36:38 -0600206 beginApplyUpdate(update, nullptr, nullptr);
Vince12e49462014-06-09 13:29:32 -0500207}
208
209shared_ptr<RibEntry>
210Rib::findParent(const Name& prefix) const
211{
Vince Lehman76c751c2014-11-18 17:36:38 -0600212 for (int i = prefix.size() - 1; i >= 0; i--) {
213 RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
214
215 if (it != m_rib.end()) {
216 return (it->second);
Vince12e49462014-06-09 13:29:32 -0500217 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600218 }
Vince12e49462014-06-09 13:29:32 -0500219
220 return shared_ptr<RibEntry>();
221}
222
223std::list<shared_ptr<RibEntry> >
224Rib::findDescendants(const Name& prefix) const
225{
226 std::list<shared_ptr<RibEntry> > children;
227
228 RibTable::const_iterator it = m_rib.find(prefix);
229
Vince Lehman76c751c2014-11-18 17:36:38 -0600230 if (it != m_rib.end()) {
231 ++it;
232 for (; it != m_rib.end(); ++it) {
233 if (prefix.isPrefixOf(it->first)) {
234 children.push_back((it->second));
235 }
236 else {
237 break;
238 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700239 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600240 }
241
242 return children;
243}
244
245std::list<shared_ptr<RibEntry>>
246Rib::findDescendantsForNonInsertedName(const Name& prefix) const
247{
248 std::list<shared_ptr<RibEntry>> children;
249
250 for (std::pair<Name, shared_ptr<RibEntry>> pair : m_rib) {
251 if (prefix.isPrefixOf(pair.first)) {
252 children.push_back(pair.second);
253 }
254 }
Vince12e49462014-06-09 13:29:32 -0500255
256 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700257}
258
Vince12e49462014-06-09 13:29:32 -0500259Rib::RibTable::iterator
260Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700261{
Vince12e49462014-06-09 13:29:32 -0500262 // Entry does not exist
Vince Lehman76c751c2014-11-18 17:36:38 -0600263 if (it == m_rib.end()) {
264 return m_rib.end();
265 }
Vince12e49462014-06-09 13:29:32 -0500266
267 shared_ptr<RibEntry> entry(it->second);
268
269 shared_ptr<RibEntry> parent = entry->getParent();
270
271 // Remove self from parent's children
Vince Lehman76c751c2014-11-18 17:36:38 -0600272 if (parent != nullptr) {
273 parent->removeChild(entry);
274 }
275
276 for (auto childIt = entry->getChildren().begin(); childIt != entry->getChildren().end(); ) {
277 shared_ptr<RibEntry> child = *childIt;
278
279 // Advance iterator so it is not invalidated by removal
280 ++childIt;
281
282 // Remove children from self
283 entry->removeChild(child);
284
285 // Update parent's children
286 if (parent != nullptr) {
287 parent->addChild(child);
Vince12e49462014-06-09 13:29:32 -0500288 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600289 }
Vince12e49462014-06-09 13:29:32 -0500290
Vince Lehman76c751c2014-11-18 17:36:38 -0600291 RibTable::iterator nextIt = m_rib.erase(it);
Vince12e49462014-06-09 13:29:32 -0500292
Yanbiao Lic17de832014-11-21 17:51:45 -0800293 // do something after erasing an entry.
294 afterEraseEntry(entry->getName());
295
Vince12e49462014-06-09 13:29:32 -0500296 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700297}
298
Vince Lehman218be0a2015-01-15 17:25:20 -0600299Rib::RouteSet
300Rib::getAncestorRoutes(const RibEntry& entry) const
Vince Lehman4387e782014-06-19 16:57:45 -0500301{
Vince Lehman218be0a2015-01-15 17:25:20 -0600302 RouteSet ancestorRoutes(&sortRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500303
304 shared_ptr<RibEntry> parent = entry.getParent();
305
Vince Lehman76c751c2014-11-18 17:36:38 -0600306 while (parent != nullptr) {
307 for (const Route& route : parent->getRoutes()) {
308 if (route.isChildInherit()) {
309 ancestorRoutes.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500310 }
Vince Lehman4387e782014-06-19 16:57:45 -0500311 }
312
Vince Lehman76c751c2014-11-18 17:36:38 -0600313 if (parent->hasCapture()) {
314 break;
Vince Lehman4387e782014-06-19 16:57:45 -0500315 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600316
317 parent = parent->getParent();
318 }
319
320 return ancestorRoutes;
321}
322
323Rib::RouteSet
324Rib::getAncestorRoutes(const Name& name) const
325{
326 RouteSet ancestorRoutes(&sortRoutes);
327
328 shared_ptr<RibEntry> parent = findParent(name);
329
330 while (parent != nullptr) {
331 for (const Route& route : parent->getRoutes()) {
332 if (route.isChildInherit()) {
333 ancestorRoutes.insert(route);
334 }
335 }
336
337 if (parent->hasCapture()) {
338 break;
339 }
340
341 parent = parent->getParent();
342 }
343
344 return ancestorRoutes;
345}
346
347void
348Rib::beginApplyUpdate(const RibUpdate& update,
349 const Rib::UpdateSuccessCallback& onSuccess,
350 const Rib::UpdateFailureCallback& onFailure)
351{
352 BOOST_ASSERT(m_fibUpdater != nullptr);
353
354 addUpdateToQueue(update, onSuccess, onFailure);
355
356 sendBatchFromQueue();
357}
358
359void
360Rib::beginRemoveFace(uint64_t faceId)
361{
362 for (const auto& nameAndRoute : findRoutesWithFaceId(faceId)) {
363 RibUpdate update;
364 update.setAction(RibUpdate::REMOVE_FACE)
365 .setName(nameAndRoute.first)
366 .setRoute(nameAndRoute.second);
367
368 addUpdateToQueue(update, nullptr, nullptr);
369 }
370
371 sendBatchFromQueue();
372}
373
374void
375Rib::addUpdateToQueue(const RibUpdate& update,
376 const Rib::UpdateSuccessCallback& onSuccess,
377 const Rib::UpdateFailureCallback& onFailure)
378{
379 RibUpdateBatch batch(update.getRoute().faceId);
380 batch.add(update);
381
382 UpdateQueueItem item{batch, onSuccess, onFailure};
383 m_updateBatches.push_back(std::move(item));
384}
385
386void
387Rib::sendBatchFromQueue()
388{
389 if (m_updateBatches.empty() || m_isUpdateInProgress) {
390 return;
391 }
392
393 m_isUpdateInProgress = true;
394
395 UpdateQueueItem item = std::move(m_updateBatches.front());
396 m_updateBatches.pop_front();
397
398 RibUpdateBatch& batch = item.batch;
399
400 // Until task #1698, each RibUpdateBatch contains exactly one RIB update
401 BOOST_ASSERT(batch.size() == 1);
402
403 const Rib::UpdateSuccessCallback& managerSuccessCallback = item.managerSuccessCallback;
404 const Rib::UpdateFailureCallback& managerFailureCallback = item.managerFailureCallback;
405
406 m_fibUpdater->computeAndSendFibUpdates(batch,
407 bind(&Rib::onFibUpdateSuccess, this,
408 batch, _1, managerSuccessCallback),
409 bind(&Rib::onFibUpdateFailure, this,
410 managerFailureCallback, _1, _2));
411
412 if (m_onSendBatchFromQueue != nullptr) {
413 m_onSendBatchFromQueue(batch);
414 }
415}
416
417void
418Rib::onFibUpdateSuccess(const RibUpdateBatch& batch,
419 const RibUpdateList& inheritedRoutes,
420 const Rib::UpdateSuccessCallback& onSuccess)
421{
422 for (const RibUpdate& update : batch) {
423 switch (update.getAction()) {
424 case RibUpdate::REGISTER:
425 insert(update.getName(), update.getRoute());
426 break;
427 case RibUpdate::UNREGISTER:
428 case RibUpdate::REMOVE_FACE:
429 erase(update.getName(), update.getRoute());
430 break;
431 }
432 }
433
434 // Add and remove precalculated inherited routes to RibEntries
435 modifyInheritedRoutes(inheritedRoutes);
436
437 m_isUpdateInProgress = false;
438
439 if (onSuccess != nullptr) {
440 onSuccess();
441 }
442
443 // Try to advance the batch queue
444 sendBatchFromQueue();
445}
446
447void
448Rib::onFibUpdateFailure(const Rib::UpdateFailureCallback& onFailure,
449 uint32_t code, const std::string& error)
450{
451 m_isUpdateInProgress = false;
452
453 if (onFailure != nullptr) {
454 onFailure(code, error);
455 }
456
457 // Try to advance the batch queue
458 sendBatchFromQueue();
459}
460
461void
462Rib::modifyInheritedRoutes(const RibUpdateList& inheritedRoutes)
463{
464 for (const RibUpdate& update : inheritedRoutes) {
465 RibTable::iterator ribIt = m_rib.find(update.getName());
466
467 BOOST_ASSERT(ribIt != m_rib.end());
468 shared_ptr<RibEntry> entry(ribIt->second);
469
470 switch (update.getAction()) {
471 case RibUpdate::REGISTER:
472 entry->addInheritedRoute(update.getRoute());
473 break;
474 case RibUpdate::UNREGISTER:
475 entry->removeInheritedRoute(update.getRoute());
476 break;
477 case RibUpdate::REMOVE_FACE:
478 break;
479 }
480 }
481}
482
483std::list<Rib::NameAndRoute>
484Rib::findRoutesWithFaceId(uint64_t faceId)
485{
486 std::list<NameAndRoute> routes;
487
488 FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
489
490 // No RIB entries have this face
491 if (lookupIt == m_faceMap.end()) {
492 return routes;
493 }
494
495 RibEntryList& ribEntries = lookupIt->second;
496
497 // For each RIB entry that has faceId
498 for (const shared_ptr<RibEntry>& entry : ribEntries) {
499 // Find the routes in the entry
500 for (const Route& route : *entry) {
501 if (route.faceId == faceId) {
502 routes.push_back(NameAndRoute(entry->getName(), route));
503 }
504 }
505 }
506
507 return routes;
Vince Lehman4387e782014-06-19 16:57:45 -0500508}
509
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700510std::ostream&
Vince12e49462014-06-09 13:29:32 -0500511operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700512{
Vince Lehman76c751c2014-11-18 17:36:38 -0600513 for (const auto& item : rib) {
Weiwei Liuaaa58a62016-11-28 23:15:15 -0700514 os << *item.second << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600515 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700516
517 return os;
518}
519
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700520} // namespace rib
521} // namespace nfd