30 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
35 using ndn::nfd::ControlParameters;
39 const unsigned int FibUpdater::MAX_NUM_TIMEOUTS = 10;
40 const uint32_t FibUpdater::ERROR_FACE_NOT_FOUND = 410;
44 , m_controller(controller)
57 m_inheritedRoutes.clear();
60 m_updatesForBatchFaceId.clear();
61 m_updatesForNonBatchFaceId.clear();
63 computeUpdates(batch);
65 sendUpdatesForBatchFaceId(onSuccess, onFailure);
76 switch(update.getAction()) {
78 computeUpdatesForRegistration(update);
81 computeUpdatesForUnregistration(update);
84 computeUpdatesForUnregistration(update);
88 m_updatesForBatchFaceId.clear();
95 FibUpdater::computeUpdatesForRegistration(
const RibUpdate& update)
97 const Name& prefix = update.getName();
98 const Route& route = update.getRoute();
103 if (it != m_rib.
end()) {
104 shared_ptr<const RibEntry> entry(it->second);
109 if (existingRoute == entry->end()) {
111 bool willCaptureBeTurnedOn = (entry->hasCapture() ==
false && route.isCapture());
113 createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
117 RibEntry entryCopy = *entry;
119 Route& routeToUpdate = *(entryCopy.findRoute(route));
121 routeToUpdate.flags = route.flags;
122 routeToUpdate.cost = route.cost;
123 routeToUpdate.expires = route.expires;
125 createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
131 shared_ptr<RibEntry> parent = m_rib.
findParent(prefix);
136 for (
const auto& descendant : descendants) {
139 if (descendant->getParent() == parent) {
140 children.push_back(descendant);
144 createFibUpdatesForNewRibEntry(prefix, route, children);
149 FibUpdater::computeUpdatesForUnregistration(
const RibUpdate& update)
151 const Name& prefix = update.getName();
152 const Route& route = update.getRoute();
157 if (ribIt != m_rib.
end()) {
158 shared_ptr<const RibEntry> entry(ribIt->second);
160 const bool hadCapture = entry->hasCapture();
164 if (existing != entry->end()) {
165 RibEntry temp = *entry;
168 temp.eraseRoute(route);
170 const bool captureWasTurnedOff = (hadCapture && !temp.hasCapture());
172 createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
176 const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.faceId);
178 if (next !=
nullptr) {
179 createFibUpdatesForNewRoute(temp, *next,
false);
183 if (entry->getNRoutes() == 1) {
184 createFibUpdatesForErasedRibEntry(*entry);
191 FibUpdater::sendUpdates(
const FibUpdateList& updates,
192 const FibUpdateSuccessCallback& onSuccess,
193 const FibUpdateFailureCallback& onFailure)
195 std::string updateString = (updates.size() == 1) ?
" update" :
" updates";
196 NFD_LOG_DEBUG(
"Applying " << updates.size() << updateString <<
" to FIB");
198 for (
const FibUpdate& update : updates) {
202 sendAddNextHopUpdate(update, onSuccess, onFailure);
205 sendRemoveNextHopUpdate(update, onSuccess, onFailure);
211 FibUpdater::sendUpdatesForBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
212 const FibUpdateFailureCallback& onFailure)
214 if (m_updatesForBatchFaceId.size() > 0) {
215 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
218 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
223 FibUpdater::sendUpdatesForNonBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
224 const FibUpdateFailureCallback& onFailure)
226 if (m_updatesForNonBatchFaceId.size() > 0) {
227 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
230 onSuccess(m_inheritedRoutes);
235 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
236 const FibUpdateSuccessCallback& onSuccess,
237 const FibUpdateFailureCallback& onFailure,
240 m_controller.start<ndn::nfd::FibAddNextHopCommand>(
242 .setName(update.name)
243 .setFaceId(update.faceId)
244 .setCost(update.cost),
245 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
246 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
250 FibUpdater::sendRemoveNextHopUpdate(
const FibUpdate& update,
251 const FibUpdateSuccessCallback& onSuccess,
252 const FibUpdateFailureCallback& onFailure,
255 m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
257 .setName(update.name)
258 .setFaceId(update.faceId),
259 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
260 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
264 FibUpdater::onUpdateSuccess(
const FibUpdate update,
265 const FibUpdateSuccessCallback& onSuccess,
266 const FibUpdateFailureCallback& onFailure)
268 if (update.faceId == m_batchFaceId) {
269 m_updatesForBatchFaceId.remove(update);
271 if (m_updatesForBatchFaceId.size() == 0) {
272 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
276 m_updatesForNonBatchFaceId.remove(update);
278 if (m_updatesForNonBatchFaceId.size() == 0) {
279 onSuccess(m_inheritedRoutes);
285 FibUpdater::onUpdateError(
const FibUpdate update,
286 const FibUpdateSuccessCallback& onSuccess,
287 const FibUpdateFailureCallback& onFailure,
288 const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
290 uint32_t code = response.getCode();
292 " (code: " << code <<
", error: " << response.getText() <<
")");
294 if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts < MAX_NUM_TIMEOUTS) {
295 sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
297 else if (code == ERROR_FACE_NOT_FOUND) {
298 if (update.faceId == m_batchFaceId) {
299 onFailure(code, response.getText());
302 m_updatesForNonBatchFaceId.remove(update);
304 if (m_updatesForNonBatchFaceId.size() == 0) {
305 onSuccess(m_inheritedRoutes);
310 BOOST_THROW_EXCEPTION(Error(
"Non-recoverable error: " + response.getText() +
311 " code: " + to_string(code)));
316 FibUpdater::addFibUpdate(FibUpdate update)
318 FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
319 m_updatesForNonBatchFaceId;
324 [&update] (
const FibUpdate& other) {
325 return update.name == other.name && update.faceId == other.faceId;
328 if (it != updates.end()) {
329 FibUpdate& existingUpdate = *it;
330 existingUpdate.action = update.action;
331 existingUpdate.cost = update.cost;
334 updates.push_back(update);
339 FibUpdater::addInheritedRoutes(
const RibEntry& entry,
const Rib::RouteSet& routesToAdd)
341 for (
const Route& route : routesToAdd) {
343 if (!entry.hasFaceId(route.faceId)) {
345 addInheritedRoute(entry.getName(), route);
353 FibUpdater::addInheritedRoutes(
const Name& name,
const Rib::RouteSet& routesToAdd,
356 for (
const Route& route : routesToAdd) {
357 if (route.faceId != ignore.faceId) {
359 addInheritedRoute(name, route);
367 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
369 for (
const Route& route : routesToRemove) {
371 if (entry.hasInheritedRoute(route)) {
372 removeInheritedRoute(entry.getName(), route);
379 FibUpdater::createFibUpdatesForNewRibEntry(
const Name& name,
const Route& route,
386 if (!route.isChildInherit() && !route.isCapture()) {
388 addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
390 else if (route.isChildInherit() && route.isCapture()) {
393 routesToAdd.insert(route);
396 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
398 else if (route.isChildInherit()) {
399 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
402 addInheritedRoutes(name, ancestorRoutes, route);
409 if (it != ancestorRoutes.end()) {
410 ancestorRoutes.erase(it);
414 ancestorRoutes.insert(route);
417 modifyChildrensInheritedRoutes(children, ancestorRoutes,
Rib::RouteSet());
419 else if (route.isCapture()) {
421 modifyChildrensInheritedRoutes(children,
Rib::RouteSet(), m_rib.getAncestorRoutes(name));
426 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
427 bool captureWasTurnedOn)
430 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
433 if (route.isChildInherit()) {
437 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
439 routesToAdd.insert(route);
444 if (captureWasTurnedOn) {
446 routesToRemove = m_rib.getAncestorRoutes(entry);
449 removeInheritedRoutes(entry, routesToRemove);
452 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
457 const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
459 if (other ==
nullptr || route.cost <= other->cost) {
465 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
466 const Route& existingRoute)
468 const bool costDidChange = (route.cost != existingRoute.cost);
471 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
474 if (route.flags == existingRoute.flags && !costDidChange) {
481 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
485 else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
493 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
496 if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
499 routesToAdd.insert(route);
500 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
508 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
511 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
514 routesToAdd.insert(route);
515 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
518 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
521 routesToRemove.insert(route);
525 if (prevRoute !=
nullptr) {
526 routesToAdd.insert(*prevRoute);
530 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
534 if (it != ancestorRoutes.end()) {
535 routesToAdd.insert(*it);
539 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
543 if (!existingRoute.isCapture() && route.isCapture()) {
544 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
547 removeInheritedRoutes(entry, ancestorRoutes);
550 modifyChildrensInheritedRoutes(entry.getChildren(),
Rib::RouteSet(), ancestorRoutes);
552 else if (existingRoute.isCapture() && !route.isCapture()) {
553 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
556 addInheritedRoutes(entry, ancestorRoutes);
559 modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes,
Rib::RouteSet());
564 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
565 const bool captureWasTurnedOff)
569 if (route.isChildInherit() && route.isCapture()) {
572 routesToRemove.insert(route);
577 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
579 routesToAdd = m_rib.getAncestorRoutes(entry);
582 addInheritedRoutes(entry, routesToAdd);
585 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
587 else if (route.isChildInherit()) {
590 if (!entry.hasCapture()) {
591 routesToAdd = m_rib.getAncestorRoutes(entry);
595 routesToRemove.insert(route);
598 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
600 else if (route.isCapture()) {
604 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
606 routesToAdd = m_rib.getAncestorRoutes(entry);
609 addInheritedRoutes(entry, routesToAdd);
612 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
616 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
619 if (!entry.hasCapture() && entry.getNRoutes() != 0) {
624 if (it != ancestorRoutes.end()) {
625 addInheritedRoute(entry.getName(), *it);
632 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
634 for (
const Route& route : entry.getInheritedRoutes()) {
644 for (
const auto& child : children) {
645 traverseSubTree(*child, routesToAdd, routesToRemove);
650 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
651 Rib::Rib::RouteSet routesToRemove)
654 if (entry.hasCapture()) {
659 for (Rib::RouteSet::const_iterator removeIt = routesToRemove.begin();
660 removeIt != routesToRemove.end(); )
664 if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
665 routesToRemove.erase(removeIt++);
670 if (entry.hasInheritedRoute(*removeIt)) {
671 removeInheritedRoute(entry.getName(), *removeIt);
679 for (Rib::RouteSet::const_iterator addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
682 if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
683 routesToAdd.erase(addIt++);
688 if (!entry.hasFaceId(addIt->faceId)) {
689 addInheritedRoute(entry.getName(), *addIt);
696 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
700 FibUpdater::addInheritedRoute(
const Name& name,
const Route& route)
707 m_inheritedRoutes.push_back(update);
711 FibUpdater::removeInheritedRoute(
const Name& name,
const Route& route)
718 m_inheritedRoutes.push_back(update);
std::list< FibUpdate > FibUpdateList
#define NFD_LOG_DEBUG(expression)
std::set< Route, RouteComparePredicate > RouteSet
An update triggered by a face destruction notification.
const_iterator find(const Name &prefix) const
function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
std::list< shared_ptr< RibEntry > > findDescendantsForNonInsertedName(const Name &prefix) const
finds namespaces under the passed prefix
represents a collection of RibUpdates to be applied to a single FaceId
void setFibUpdater(FibUpdater *updater)
const_iterator end() const
void computeAndSendFibUpdates(const RibUpdateBatch &batch, const FibUpdateSuccessCallback &onSuccess, const FibUpdateFailureCallback &onFailure)
computes FibUpdates using the provided RibUpdateBatch and then sends the updates to NFD's FIB ...
Table::const_iterator iterator
static FibUpdate createAddUpdate(const Name &name, const uint64_t faceId, const uint64_t cost)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
std::list< shared_ptr< RibEntry > > RibEntryList
RouteList::const_iterator const_iterator
FibUpdater(Rib &rib, ndn::nfd::Controller &controller)
uint64_t getFaceId() const
#define NFD_LOG_INIT(name)
RibTable::const_iterator const_iterator
function< void(uint32_t code, const std::string &error)> FibUpdateFailureCallback
static FibUpdate createRemoveUpdate(const Name &name, const uint64_t faceId)
shared_ptr< RibEntry > findParent(const Name &prefix) const