blob: a2a27fb7e3e1d88e237294b7f44463bcc75035a9 [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi89c0ea02017-03-06 19:52:05 +00003 * Copyright (c) 2014-2017, 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"
27
Vince Lehman76c751c2014-11-18 17:36:38 -060028#include "fib-updater.hpp"
Vince Lehman281ded72014-08-21 12:17:08 -050029#include "core/logger.hpp"
30
31NFD_LOG_INIT("Rib");
32
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070033namespace nfd {
34namespace rib {
35
Junxiao Shi89c0ea02017-03-06 19:52:05 +000036bool
37operator<(const RibRouteRef& lhs, const RibRouteRef& rhs)
38{
39 return std::tie(lhs.entry->getName(), lhs.route->faceId, lhs.route->origin) <
40 std::tie(rhs.entry->getName(), rhs.route->faceId, rhs.route->origin);
41}
42
Vince Lehman4387e782014-06-19 16:57:45 -050043static inline bool
Vince Lehman218be0a2015-01-15 17:25:20 -060044sortRoutes(const Route& lhs, const Route& rhs)
Vince Lehman4387e782014-06-19 16:57:45 -050045{
Vince Lehman218be0a2015-01-15 17:25:20 -060046 return lhs.faceId < rhs.faceId;
Vince Lehman4387e782014-06-19 16:57:45 -050047}
48
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070049Rib::Rib()
Vince12e49462014-06-09 13:29:32 -050050 : m_nItems(0)
Vince Lehman76c751c2014-11-18 17:36:38 -060051 , m_isUpdateInProgress(false)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070052{
53}
54
Vince Lehman76c751c2014-11-18 17:36:38 -060055Rib::~Rib()
56{
57}
58
59void
60Rib::setFibUpdater(FibUpdater* updater)
61{
62 m_fibUpdater = updater;
63}
64
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070065Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050066Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070067{
Vince12e49462014-06-09 13:29:32 -050068 return m_rib.find(prefix);
69}
70
Vince Lehman218be0a2015-01-15 17:25:20 -060071Route*
72Rib::find(const Name& prefix, const Route& route) const
Vince12e49462014-06-09 13:29:32 -050073{
74 RibTable::const_iterator ribIt = m_rib.find(prefix);
75
76 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060077 if (ribIt != m_rib.end()) {
78 shared_ptr<RibEntry> entry = ribIt->second;
Vince12e49462014-06-09 13:29:32 -050079
Vince Lehman76c751c2014-11-18 17:36:38 -060080 RibEntry::iterator routeIt = entry->findRoute(route);
Vince12e49462014-06-09 13:29:32 -050081
Vince Lehman76c751c2014-11-18 17:36:38 -060082 if (routeIt != entry->end()) {
83 return &((*routeIt));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070084 }
Vince Lehman76c751c2014-11-18 17:36:38 -060085 }
Vince Lehman218be0a2015-01-15 17:25:20 -060086
87 return nullptr;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070088}
89
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070090void
Vince Lehman218be0a2015-01-15 17:25:20 -060091Rib::insert(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070092{
Vince12e49462014-06-09 13:29:32 -050093 RibTable::iterator ribIt = m_rib.find(prefix);
94
95 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060096 if (ribIt != m_rib.end()) {
97 shared_ptr<RibEntry> entry(ribIt->second);
Vince12e49462014-06-09 13:29:32 -050098
Nick Gordon89c4cca2016-11-02 15:42:32 +000099 RibEntry::iterator entryIt;
100 bool didInsert = false;
101 std::tie(entryIt, didInsert) = entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -0500102
Nick Gordon89c4cca2016-11-02 15:42:32 +0000103 if (didInsert) {
104 // The route was new and we successfully inserted it.
Vince Lehman76c751c2014-11-18 17:36:38 -0600105 m_nItems++;
Vince12e49462014-06-09 13:29:32 -0500106
Nick Gordon89c4cca2016-11-02 15:42:32 +0000107 afterAddRoute(RibRouteRef{entry, entryIt});
108
Vince12e49462014-06-09 13:29:32 -0500109 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600110 m_faceMap[route.faceId].push_back(entry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700111 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600112 else {
113 // Route exists, update fields
114 // First cancel old scheduled event, if any, then set the EventId to new one
Nick Gordon89c4cca2016-11-02 15:42:32 +0000115 if (static_cast<bool>(entryIt->getExpirationEvent())) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600116 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
Nick Gordon89c4cca2016-11-02 15:42:32 +0000117 << (*entryIt));
118 scheduler::cancel(entryIt->getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600119 }
120
121 // No checks are required here as the iterator needs to be updated in all cases.
Nick Gordon89c4cca2016-11-02 15:42:32 +0000122 entryIt->setExpirationEvent(route.getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600123
Nick Gordon89c4cca2016-11-02 15:42:32 +0000124 entryIt->flags = route.flags;
125 entryIt->cost = route.cost;
126 entryIt->expires = route.expires;
Vince Lehman76c751c2014-11-18 17:36:38 -0600127 }
128 }
129 else {
130 // New name prefix
Nick Gordon89c4cca2016-11-02 15:42:32 +0000131 shared_ptr<RibEntry> entry = make_shared<RibEntry>();
Vince Lehman76c751c2014-11-18 17:36:38 -0600132
133 m_rib[prefix] = entry;
134 m_nItems++;
135
136 entry->setName(prefix);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000137 RibEntry::iterator routeIt = entry->insertRoute(route).first;
Vince Lehman76c751c2014-11-18 17:36:38 -0600138
139 // Find prefix's parent
140 shared_ptr<RibEntry> parent = findParent(prefix);
141
142 // Add self to parent's children
143 if (parent != nullptr) {
144 parent->addChild(entry);
145 }
146
147 RibEntryList children = findDescendants(prefix);
148
149 for (const auto& child : children) {
150 if (child->getParent() == parent) {
151 // Remove child from parent and inherit parent's child
152 if (parent != nullptr) {
153 parent->removeChild(child);
154 }
155
156 entry->addChild(child);
157 }
158 }
159
160 // Register with face lookup table
161 m_faceMap[route.faceId].push_back(entry);
162
163 // do something after inserting an entry
164 afterInsertEntry(prefix);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000165 afterAddRoute(RibRouteRef{entry, routeIt});
Vince Lehman76c751c2014-11-18 17:36:38 -0600166 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700167}
168
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700169void
Vince Lehman218be0a2015-01-15 17:25:20 -0600170Rib::erase(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700171{
Vince12e49462014-06-09 13:29:32 -0500172 RibTable::iterator ribIt = m_rib.find(prefix);
173
174 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -0600175 if (ribIt != m_rib.end()) {
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000176 shared_ptr<RibEntry> entry = ribIt->second;
Vince Lehman76c751c2014-11-18 17:36:38 -0600177 RibEntry::iterator routeIt = entry->findRoute(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500178
Vince Lehman76c751c2014-11-18 17:36:38 -0600179 if (routeIt != entry->end()) {
Nick Gordon89c4cca2016-11-02 15:42:32 +0000180 beforeRemoveRoute(RibRouteRef{entry, routeIt});
181
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000182 auto faceId = route.faceId;
Vince Lehman76c751c2014-11-18 17:36:38 -0600183 entry->eraseRoute(routeIt);
184 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500185
Vince Lehman76c751c2014-11-18 17:36:38 -0600186 // If this RibEntry no longer has this faceId, unregister from face lookup table
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000187 if (!entry->hasFaceId(faceId)) {
188 m_faceMap[faceId].remove(entry);
Vince Lehman76c751c2014-11-18 17:36:38 -0600189 }
Syed Obaid3313a372014-07-01 01:31:33 -0500190
Vince Lehman76c751c2014-11-18 17:36:38 -0600191 // If a RibEntry's route list is empty, remove it from the tree
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000192 if (entry->getRoutes().empty()) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600193 eraseEntry(ribIt);
194 }
Vince12e49462014-06-09 13:29:32 -0500195 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600196 }
Vince12e49462014-06-09 13:29:32 -0500197}
198
199void
Vince Lehman76c751c2014-11-18 17:36:38 -0600200Rib::onRouteExpiration(const Name& prefix, const Route& route)
Vince12e49462014-06-09 13:29:32 -0500201{
Vince Lehman76c751c2014-11-18 17:36:38 -0600202 NFD_LOG_DEBUG(route << " for " << prefix << " has expired");
Vince12e49462014-06-09 13:29:32 -0500203
Vince Lehman76c751c2014-11-18 17:36:38 -0600204 RibUpdate update;
205 update.setAction(RibUpdate::UNREGISTER)
206 .setName(prefix)
207 .setRoute(route);
Vince12e49462014-06-09 13:29:32 -0500208
Vince Lehman76c751c2014-11-18 17:36:38 -0600209 beginApplyUpdate(update, nullptr, nullptr);
Vince12e49462014-06-09 13:29:32 -0500210}
211
212shared_ptr<RibEntry>
213Rib::findParent(const Name& prefix) const
214{
Vince Lehman76c751c2014-11-18 17:36:38 -0600215 for (int i = prefix.size() - 1; i >= 0; i--) {
216 RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
217
218 if (it != m_rib.end()) {
219 return (it->second);
Vince12e49462014-06-09 13:29:32 -0500220 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600221 }
Vince12e49462014-06-09 13:29:32 -0500222
223 return shared_ptr<RibEntry>();
224}
225
226std::list<shared_ptr<RibEntry> >
227Rib::findDescendants(const Name& prefix) const
228{
229 std::list<shared_ptr<RibEntry> > children;
230
231 RibTable::const_iterator it = m_rib.find(prefix);
232
Vince Lehman76c751c2014-11-18 17:36:38 -0600233 if (it != m_rib.end()) {
234 ++it;
235 for (; it != m_rib.end(); ++it) {
236 if (prefix.isPrefixOf(it->first)) {
237 children.push_back((it->second));
238 }
239 else {
240 break;
241 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700242 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600243 }
244
245 return children;
246}
247
248std::list<shared_ptr<RibEntry>>
249Rib::findDescendantsForNonInsertedName(const Name& prefix) const
250{
251 std::list<shared_ptr<RibEntry>> children;
252
253 for (std::pair<Name, shared_ptr<RibEntry>> pair : m_rib) {
254 if (prefix.isPrefixOf(pair.first)) {
255 children.push_back(pair.second);
256 }
257 }
Vince12e49462014-06-09 13:29:32 -0500258
259 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700260}
261
Vince12e49462014-06-09 13:29:32 -0500262Rib::RibTable::iterator
263Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700264{
Vince12e49462014-06-09 13:29:32 -0500265 // Entry does not exist
Vince Lehman76c751c2014-11-18 17:36:38 -0600266 if (it == m_rib.end()) {
267 return m_rib.end();
268 }
Vince12e49462014-06-09 13:29:32 -0500269
270 shared_ptr<RibEntry> entry(it->second);
271
272 shared_ptr<RibEntry> parent = entry->getParent();
273
274 // Remove self from parent's children
Vince Lehman76c751c2014-11-18 17:36:38 -0600275 if (parent != nullptr) {
276 parent->removeChild(entry);
277 }
278
279 for (auto childIt = entry->getChildren().begin(); childIt != entry->getChildren().end(); ) {
280 shared_ptr<RibEntry> child = *childIt;
281
282 // Advance iterator so it is not invalidated by removal
283 ++childIt;
284
285 // Remove children from self
286 entry->removeChild(child);
287
288 // Update parent's children
289 if (parent != nullptr) {
290 parent->addChild(child);
Vince12e49462014-06-09 13:29:32 -0500291 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600292 }
Vince12e49462014-06-09 13:29:32 -0500293
Vince Lehman76c751c2014-11-18 17:36:38 -0600294 RibTable::iterator nextIt = m_rib.erase(it);
Vince12e49462014-06-09 13:29:32 -0500295
Yanbiao Lic17de832014-11-21 17:51:45 -0800296 // do something after erasing an entry.
297 afterEraseEntry(entry->getName());
298
Vince12e49462014-06-09 13:29:32 -0500299 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700300}
301
Vince Lehman218be0a2015-01-15 17:25:20 -0600302Rib::RouteSet
303Rib::getAncestorRoutes(const RibEntry& entry) const
Vince Lehman4387e782014-06-19 16:57:45 -0500304{
Vince Lehman218be0a2015-01-15 17:25:20 -0600305 RouteSet ancestorRoutes(&sortRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500306
307 shared_ptr<RibEntry> parent = entry.getParent();
308
Vince Lehman76c751c2014-11-18 17:36:38 -0600309 while (parent != nullptr) {
310 for (const Route& route : parent->getRoutes()) {
311 if (route.isChildInherit()) {
312 ancestorRoutes.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500313 }
Vince Lehman4387e782014-06-19 16:57:45 -0500314 }
315
Vince Lehman76c751c2014-11-18 17:36:38 -0600316 if (parent->hasCapture()) {
317 break;
Vince Lehman4387e782014-06-19 16:57:45 -0500318 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600319
320 parent = parent->getParent();
321 }
322
323 return ancestorRoutes;
324}
325
326Rib::RouteSet
327Rib::getAncestorRoutes(const Name& name) const
328{
329 RouteSet ancestorRoutes(&sortRoutes);
330
331 shared_ptr<RibEntry> parent = findParent(name);
332
333 while (parent != nullptr) {
334 for (const Route& route : parent->getRoutes()) {
335 if (route.isChildInherit()) {
336 ancestorRoutes.insert(route);
337 }
338 }
339
340 if (parent->hasCapture()) {
341 break;
342 }
343
344 parent = parent->getParent();
345 }
346
347 return ancestorRoutes;
348}
349
350void
351Rib::beginApplyUpdate(const RibUpdate& update,
352 const Rib::UpdateSuccessCallback& onSuccess,
353 const Rib::UpdateFailureCallback& onFailure)
354{
355 BOOST_ASSERT(m_fibUpdater != nullptr);
356
357 addUpdateToQueue(update, onSuccess, onFailure);
358
359 sendBatchFromQueue();
360}
361
362void
363Rib::beginRemoveFace(uint64_t faceId)
364{
365 for (const auto& nameAndRoute : findRoutesWithFaceId(faceId)) {
366 RibUpdate update;
367 update.setAction(RibUpdate::REMOVE_FACE)
368 .setName(nameAndRoute.first)
369 .setRoute(nameAndRoute.second);
370
371 addUpdateToQueue(update, nullptr, nullptr);
372 }
373
374 sendBatchFromQueue();
375}
376
377void
378Rib::addUpdateToQueue(const RibUpdate& update,
379 const Rib::UpdateSuccessCallback& onSuccess,
380 const Rib::UpdateFailureCallback& onFailure)
381{
382 RibUpdateBatch batch(update.getRoute().faceId);
383 batch.add(update);
384
385 UpdateQueueItem item{batch, onSuccess, onFailure};
386 m_updateBatches.push_back(std::move(item));
387}
388
389void
390Rib::sendBatchFromQueue()
391{
392 if (m_updateBatches.empty() || m_isUpdateInProgress) {
393 return;
394 }
395
396 m_isUpdateInProgress = true;
397
398 UpdateQueueItem item = std::move(m_updateBatches.front());
399 m_updateBatches.pop_front();
400
401 RibUpdateBatch& batch = item.batch;
402
403 // Until task #1698, each RibUpdateBatch contains exactly one RIB update
404 BOOST_ASSERT(batch.size() == 1);
405
406 const Rib::UpdateSuccessCallback& managerSuccessCallback = item.managerSuccessCallback;
407 const Rib::UpdateFailureCallback& managerFailureCallback = item.managerFailureCallback;
408
409 m_fibUpdater->computeAndSendFibUpdates(batch,
410 bind(&Rib::onFibUpdateSuccess, this,
411 batch, _1, managerSuccessCallback),
412 bind(&Rib::onFibUpdateFailure, this,
413 managerFailureCallback, _1, _2));
414
415 if (m_onSendBatchFromQueue != nullptr) {
416 m_onSendBatchFromQueue(batch);
417 }
418}
419
420void
421Rib::onFibUpdateSuccess(const RibUpdateBatch& batch,
422 const RibUpdateList& inheritedRoutes,
423 const Rib::UpdateSuccessCallback& onSuccess)
424{
425 for (const RibUpdate& update : batch) {
426 switch (update.getAction()) {
427 case RibUpdate::REGISTER:
428 insert(update.getName(), update.getRoute());
429 break;
430 case RibUpdate::UNREGISTER:
431 case RibUpdate::REMOVE_FACE:
432 erase(update.getName(), update.getRoute());
433 break;
434 }
435 }
436
437 // Add and remove precalculated inherited routes to RibEntries
438 modifyInheritedRoutes(inheritedRoutes);
439
440 m_isUpdateInProgress = false;
441
442 if (onSuccess != nullptr) {
443 onSuccess();
444 }
445
446 // Try to advance the batch queue
447 sendBatchFromQueue();
448}
449
450void
451Rib::onFibUpdateFailure(const Rib::UpdateFailureCallback& onFailure,
452 uint32_t code, const std::string& error)
453{
454 m_isUpdateInProgress = false;
455
456 if (onFailure != nullptr) {
457 onFailure(code, error);
458 }
459
460 // Try to advance the batch queue
461 sendBatchFromQueue();
462}
463
464void
465Rib::modifyInheritedRoutes(const RibUpdateList& inheritedRoutes)
466{
467 for (const RibUpdate& update : inheritedRoutes) {
468 RibTable::iterator ribIt = m_rib.find(update.getName());
469
470 BOOST_ASSERT(ribIt != m_rib.end());
471 shared_ptr<RibEntry> entry(ribIt->second);
472
473 switch (update.getAction()) {
474 case RibUpdate::REGISTER:
475 entry->addInheritedRoute(update.getRoute());
476 break;
477 case RibUpdate::UNREGISTER:
478 entry->removeInheritedRoute(update.getRoute());
479 break;
480 case RibUpdate::REMOVE_FACE:
481 break;
482 }
483 }
484}
485
486std::list<Rib::NameAndRoute>
487Rib::findRoutesWithFaceId(uint64_t faceId)
488{
489 std::list<NameAndRoute> routes;
490
491 FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
492
493 // No RIB entries have this face
494 if (lookupIt == m_faceMap.end()) {
495 return routes;
496 }
497
498 RibEntryList& ribEntries = lookupIt->second;
499
500 // For each RIB entry that has faceId
501 for (const shared_ptr<RibEntry>& entry : ribEntries) {
502 // Find the routes in the entry
503 for (const Route& route : *entry) {
504 if (route.faceId == faceId) {
505 routes.push_back(NameAndRoute(entry->getName(), route));
506 }
507 }
508 }
509
510 return routes;
Vince Lehman4387e782014-06-19 16:57:45 -0500511}
512
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700513std::ostream&
Vince12e49462014-06-09 13:29:32 -0500514operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700515{
Vince Lehman76c751c2014-11-18 17:36:38 -0600516 for (const auto& item : rib) {
Weiwei Liuaaa58a62016-11-28 23:15:15 -0700517 os << *item.second << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600518 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700519
520 return os;
521}
522
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700523} // namespace rib
524} // namespace nfd