blob: ee820f69f174acebd62b9d79d996b242418a123b [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_DAEMON_RIB_FIB_UPDATER_HPP
#define NFD_DAEMON_RIB_FIB_UPDATER_HPP
#include "core/common.hpp"
#include "fib-update.hpp"
#include "rib.hpp"
#include "rib-update-batch.hpp"
#include <ndn-cxx/mgmt/nfd/controller.hpp>
namespace nfd::rib {
/**
* \brief Computes FibUpdates based on updates to the RIB and sends them to NFD.
*/
class FibUpdater : noncopyable
{
public:
class Error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
using FibUpdateList = std::list<FibUpdate>;
using FibUpdateSuccessCallback = std::function<void(RibUpdateList inheritedRoutes)>;
using FibUpdateFailureCallback = std::function<void(uint32_t code, const std::string& error)>;
FibUpdater(Rib& rib, ndn::nfd::Controller& controller);
#ifdef NFD_WITH_TESTS
virtual
~FibUpdater() = default;
#endif
/** \brief Computes FibUpdates using the provided RibUpdateBatch and then sends the
* updates to NFD's FIB.
*
* \note Caller must guarantee that the previous batch has either succeeded or failed
* before calling this method
*/
void
computeAndSendFibUpdates(const RibUpdateBatch& batch,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure);
private:
/**
* \brief Determines the type of action that will be performed on the RIB and calls the
* corresponding computation method.
*/
void
computeUpdates(const RibUpdateBatch& batch);
/**
* \brief Sends the passed updates to NFD.
*
* onSuccess or onFailure will be called based on the results in
* onUpdateSuccess or onUpdateFailure.
*
* \see FibUpdater::onUpdateSuccess
* \see FibUpdater::onUpdateFailure
*/
void
sendUpdates(const FibUpdateList& updates,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure);
/**
* \brief Sends the updates in m_updatesForBatchFaceId to NFD if any exist,
* otherwise calls FibUpdater::sendUpdatesForNonBatchFaceId.
*/
void
sendUpdatesForBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure);
/**
* \brief Sends the updates in m_updatesForNonBatchFaceId to NFD if any exist,
* otherwise calls onSuccess.
*/
void
sendUpdatesForNonBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure);
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
/**
* \brief Sends a FibAddNextHopCommand to NFD using the parameters supplied by
* the passed update.
* \param nTimeouts the number of times this FibUpdate has failed due to timeout
*/
NFD_VIRTUAL_WITH_TESTS void
sendAddNextHopUpdate(const FibUpdate& update,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure,
uint32_t nTimeouts = 0);
/**
* \brief Sends a FibRemoveNextHopCommand to NFD using the parameters supplied by
* the passed update.
* \param nTimeouts the number of times this FibUpdate has failed due to timeout
*/
NFD_VIRTUAL_WITH_TESTS void
sendRemoveNextHopUpdate(const FibUpdate& update,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure,
uint32_t nTimeouts = 0);
private:
/**
* \brief Calculates the FibUpdates generated by a RIB registration.
*/
void
computeUpdatesForRegistration(const RibUpdate& update);
/**
* \brief Calculates the FibUpdates generated by a RIB unregistration.
*/
void
computeUpdatesForUnregistration(const RibUpdate& update);
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
/**
* \brief Callback used by NfdController when a FibAddNextHopCommand or FibRemoveNextHopCommand
* is successful.
*
* If the update has the same Face ID as the batch being processed, the update is
* removed from m_updatesForBatchFaceId. If m_updatesForBatchFaceId becomes empty,
* the updates with a different Face ID than the batch are sent to NFD.
*
* If the update has a different Face ID than the batch being processed, the update is
* removed from m_updatesForBatchNonFaceId. If m_updatesForBatchNonFaceId becomes empty,
* the FIB update process is considered a success.
*/
void
onUpdateSuccess(const FibUpdate& update,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure);
/**
* \brief Callback used by NfdController when a FibAddNextHopCommand or FibRemoveNextHopCommand
* is successful.
*
* If the update has not reached the max number of timeouts allowed, the update
* is retried.
*
* If the update failed due to a non-existent face and the update has the same Face ID
* as the update batch, the FIB update process fails.
*
* If the update failed due to a non-existent face and the update has a different
* face than the update batch, the update is not retried and the error is
* ignored.
*
* Otherwise, a non-recoverable error has occurred and an exception is thrown.
*/
void
onUpdateError(const FibUpdate& update,
const FibUpdateSuccessCallback& onSuccess,
const FibUpdateFailureCallback& onFailure,
const ndn::nfd::ControlResponse& response, uint32_t nTimeouts);
private:
/**
* \brief Adds the update to an update list based on its Face ID.
*
* If the update has the same Face ID as the update batch, the update is added
* to m_updatesForBatchFaceId.
*
* Otherwise, the update is added to m_updatesForBatchNonFaceId.
*/
void
addFibUpdate(const FibUpdate& update);
/**
* \brief Creates records of the passed routes added to the entry and creates FIB updates.
*/
void
addInheritedRoutes(const RibEntry& entry, const Rib::RouteSet& routesToAdd);
/**
* \brief Creates records of the passed routes added to the name and creates FIB updates.
* Routes in \p routesToAdd with the same Face ID as ignore will be not be considered.
*/
void
addInheritedRoutes(const Name& name, const Rib::RouteSet& routesToAdd, const Route& ignore);
/**
* \brief Creates records of the passed routes removed from the entry and creates FIB updates.
*/
void
removeInheritedRoutes(const RibEntry& entry, const Rib::RouteSet& routesToRemove);
/**
* \brief Calculates updates for a name that will create a new RIB entry.
*/
void
createFibUpdatesForNewRibEntry(const Name& name, const Route& route,
const Rib::RibEntryList& children);
/**
* \brief Calculates updates for a new route added to a RIB entry.
*/
void
createFibUpdatesForNewRoute(const RibEntry& entry, const Route& route,
bool captureWasTurnedOn);
/**
* \brief Calculates updates for changes to an existing route for a RIB entry.
*/
void
createFibUpdatesForUpdatedRoute(const RibEntry& entry, const Route& route,
const Route& existingRoute);
/**
* \brief Calculates updates for a an existing route removed from a RIB entry.
*/
void
createFibUpdatesForErasedRoute(const RibEntry& entry, const Route& route,
bool captureWasTurnedOff);
/**
* \brief Calculates updates for an entry that will be removed from the RIB.
*/
void
createFibUpdatesForErasedRibEntry(const RibEntry& entry);
/**
* \brief Adds and removes passed routes to children's inherited routes.
*/
void
modifyChildrensInheritedRoutes(const Rib::RibEntryList& children,
const Rib::RouteSet& routesToAdd,
const Rib::RouteSet& routesToRemove);
/**
* \brief Traverses the entry's children adding and removing the passed routes.
*/
void
traverseSubTree(const RibEntry& entry, Rib::RouteSet routesToAdd, Rib::RouteSet routesToRemove);
/**
* \brief Creates a record of a calculated inherited route that should be added to the entry.
*/
void
addInheritedRoute(const Name& name, const Route& route);
/**
* \brief Creates a record of an existing inherited route that should be removed from the entry.
*/
void
removeInheritedRoute(const Name& name, const Route& route);
private:
const Rib& m_rib;
ndn::nfd::Controller& m_controller;
uint64_t m_batchFaceId;
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
FibUpdateList m_updatesForBatchFaceId;
FibUpdateList m_updatesForNonBatchFaceId;
/**
* \brief List of inherited routes generated during FIB update calculation;
* passed to the RIB when updates are completed successfully.
*/
RibUpdateList m_inheritedRoutes;
};
} // namespace nfd::rib
#endif // NFD_DAEMON_RIB_FIB_UPDATER_HPP