rib: Generate FIB updates using route flags
refs: #1325 Change-Id: I5c567da1c06819caeba5cc5b024914666ba70ab6
This commit is contained in:
1 parent
dc26b2796a
commit
4387e78005
15 files changed
+2496
-46
No files matched your search
@@ -66,6 +66,10 @@ compareFaceId(const FaceEntry& entry, const uint64_t faceId)
|
||||
return (entry.faceId == faceId);
|
||||
}
|
||||
|
||||
// Method definition in rib-entry.cpp
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceEntry& entry);
|
||||
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
#include "fib-update.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
|
||||
shared_ptr<FibUpdate>
|
||||
FibUpdate::createAddUpdate(const Name& name, const uint64_t faceId, const uint64_t cost)
|
||||
{
|
||||
shared_ptr<FibUpdate> update = make_shared<FibUpdate>();
|
||||
|
||||
update->name = name;
|
||||
update->faceId = faceId;
|
||||
update->cost = cost;
|
||||
update->action = ADD_NEXTHOP;
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
shared_ptr<FibUpdate>
|
||||
FibUpdate::createRemoveUpdate(const Name& name, const uint64_t faceId)
|
||||
{
|
||||
shared_ptr<FibUpdate> update = make_shared<FibUpdate>();
|
||||
|
||||
update->name = name;
|
||||
update->faceId = faceId;
|
||||
update->action = REMOVE_NEXTHOP;
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,90 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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_RIB_FIB_UPDATE_HPP
|
||||
#define NFD_RIB_FIB_UPDATE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
|
||||
/** \class FibUpdate
|
||||
* \brief represents a FIB update
|
||||
*/
|
||||
class FibUpdate
|
||||
{
|
||||
public:
|
||||
FibUpdate()
|
||||
: faceId(0)
|
||||
, cost(0)
|
||||
{
|
||||
}
|
||||
|
||||
static shared_ptr<FibUpdate>
|
||||
createAddUpdate(const Name& name, const uint64_t faceId, const uint64_t cost);
|
||||
|
||||
static shared_ptr<FibUpdate>
|
||||
createRemoveUpdate(const Name& name, const uint64_t faceId);
|
||||
|
||||
enum Action
|
||||
{
|
||||
ADD_NEXTHOP = 0,
|
||||
REMOVE_NEXTHOP = 1
|
||||
};
|
||||
|
||||
public:
|
||||
Name name;
|
||||
uint64_t faceId;
|
||||
uint64_t cost;
|
||||
Action action;
|
||||
};
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const FibUpdate& update)
|
||||
{
|
||||
os << "FibUpdate("
|
||||
<< " Name: " << update.name << ", "
|
||||
<< "faceId: " << update.faceId << ", ";
|
||||
|
||||
if (update.action == FibUpdate::ADD_NEXTHOP)
|
||||
{
|
||||
os << "cost: " << update.cost << ", "
|
||||
<< "action: ADD_NEXTHOP";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "action: REMOVE_NEXTHOP";
|
||||
}
|
||||
|
||||
os << ")";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_RIB_FIB_UPDATE_HPP
|
||||
+130
-2
@@ -43,6 +43,11 @@ RibEntry::insertFace(const FaceEntry& entry)
|
||||
|
||||
if (it == end())
|
||||
{
|
||||
if (entry.flags & ndn::nfd::ROUTE_FLAG_CAPTURE)
|
||||
{
|
||||
m_nFacesWithCaptureSet++;
|
||||
}
|
||||
|
||||
m_faces.push_back(entry);
|
||||
return true;
|
||||
}
|
||||
@@ -56,8 +61,14 @@ bool
|
||||
RibEntry::eraseFace(const FaceEntry& face)
|
||||
{
|
||||
RibEntry::iterator it = std::find_if(begin(), end(), bind(&compareFaceIdAndOrigin, _1, face));
|
||||
|
||||
if (it != m_faces.end())
|
||||
{
|
||||
if (it->flags & ndn::nfd::ROUTE_FLAG_CAPTURE)
|
||||
{
|
||||
m_nFacesWithCaptureSet--;
|
||||
}
|
||||
|
||||
m_faces.erase(it);
|
||||
return true;
|
||||
}
|
||||
@@ -67,12 +78,21 @@ RibEntry::eraseFace(const FaceEntry& face)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RibEntry::hasFace(const FaceEntry& face)
|
||||
{
|
||||
RibEntry::const_iterator it = std::find_if(cbegin(), cend(),
|
||||
bind(&compareFaceIdAndOrigin, _1, face));
|
||||
|
||||
return it != cend();
|
||||
}
|
||||
|
||||
bool
|
||||
RibEntry::hasFaceId(const uint64_t faceId) const
|
||||
{
|
||||
RibEntry::const_iterator it = std::find_if(cbegin(), cend(), bind(&compareFaceId, _1, faceId));
|
||||
|
||||
return (it != cend());
|
||||
return it != cend();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -94,7 +114,115 @@ RibEntry::removeChild(shared_ptr<RibEntry> child)
|
||||
RibEntry::FaceList::iterator
|
||||
RibEntry::eraseFace(FaceList::iterator face)
|
||||
{
|
||||
return m_faces.erase(face);
|
||||
if (face != m_faces.end())
|
||||
{
|
||||
if (face->flags & ndn::nfd::ROUTE_FLAG_CAPTURE)
|
||||
{
|
||||
m_nFacesWithCaptureSet--;
|
||||
}
|
||||
|
||||
return m_faces.erase(face);
|
||||
}
|
||||
|
||||
return m_faces.end();
|
||||
}
|
||||
|
||||
void
|
||||
RibEntry::addInheritedFace(const FaceEntry& face)
|
||||
{
|
||||
m_inheritedFaces.push_back(face);
|
||||
}
|
||||
|
||||
void
|
||||
RibEntry::removeInheritedFace(const FaceEntry& face)
|
||||
{
|
||||
FaceList::iterator it = findInheritedFace(face);
|
||||
m_inheritedFaces.erase(it);
|
||||
}
|
||||
|
||||
RibEntry::FaceList::iterator
|
||||
RibEntry::findInheritedFace(const FaceEntry& face)
|
||||
{
|
||||
return std::find_if(m_inheritedFaces.begin(), m_inheritedFaces.end(),
|
||||
bind(&compareFaceId, _1, face.faceId));
|
||||
}
|
||||
|
||||
bool
|
||||
RibEntry::hasInheritedFace(const FaceEntry& face)
|
||||
{
|
||||
FaceList::const_iterator it = findInheritedFace(face);
|
||||
|
||||
return (it != m_inheritedFaces.end());
|
||||
}
|
||||
|
||||
bool
|
||||
RibEntry::hasCapture() const
|
||||
{
|
||||
return m_nFacesWithCaptureSet > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
RibEntry::hasChildInheritOnFaceId(uint64_t faceId) const
|
||||
{
|
||||
for (RibEntry::const_iterator it = m_faces.begin(); it != m_faces.end(); ++it)
|
||||
{
|
||||
if (it->faceId == faceId && (it->flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
shared_ptr<FaceEntry>
|
||||
RibEntry::getFaceWithLowestCostByFaceId(uint64_t faceId)
|
||||
{
|
||||
shared_ptr<FaceEntry> face;
|
||||
|
||||
for (FaceList::iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
// Correct face ID
|
||||
if (it->faceId == faceId)
|
||||
{
|
||||
// If this is the first face with this ID found
|
||||
if (!static_cast<bool>(face))
|
||||
{
|
||||
face = make_shared<FaceEntry>(*it);
|
||||
}
|
||||
else if (it->cost < face->cost) // Found a face with a lower cost
|
||||
{
|
||||
face = make_shared<FaceEntry>(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
shared_ptr<FaceEntry>
|
||||
RibEntry::getFaceWithLowestCostAndChildInheritByFaceId(uint64_t faceId)
|
||||
{
|
||||
shared_ptr<FaceEntry> face;
|
||||
|
||||
for (FaceList::iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
// Correct face ID and Child Inherit flag set
|
||||
if (it->faceId == faceId && it->flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
|
||||
{
|
||||
// If this is the first face with this ID found
|
||||
if (!static_cast<bool>(face))
|
||||
{
|
||||
face = make_shared<FaceEntry>(*it);
|
||||
}
|
||||
else if (it->cost < face->cost) // Found a face with a lower cost
|
||||
{
|
||||
face = make_shared<FaceEntry>(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
typedef FaceList::const_iterator const_iterator;
|
||||
|
||||
RibEntry()
|
||||
: m_nFacesWithCaptureSet(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -98,6 +99,60 @@ public:
|
||||
iterator
|
||||
findFace(const FaceEntry& face);
|
||||
|
||||
bool
|
||||
hasFace(const FaceEntry& face);
|
||||
|
||||
void
|
||||
addInheritedFace(const FaceEntry& face);
|
||||
|
||||
void
|
||||
removeInheritedFace(const FaceEntry& face);
|
||||
|
||||
/** \brief Returns the faces this namespace has inherited.
|
||||
* The inherited faces returned represent inherited entries this namespace has in the FIB.
|
||||
* \return{ faces inherited by this namespace }
|
||||
*/
|
||||
FaceList&
|
||||
getInheritedFaces();
|
||||
|
||||
/** \brief Finds an inherited face with a matching face ID.
|
||||
* \return{ An iterator to the matching face if one is found;
|
||||
* otherwise, an iterator to the end of the entry's
|
||||
* inherited face list }
|
||||
*/
|
||||
FaceList::iterator
|
||||
findInheritedFace(const FaceEntry& face);
|
||||
|
||||
/** \brief Determines if the entry has an inherited face with a matching face ID.
|
||||
* \return{ True, if a matching inherited face is found; otherwise, false. }
|
||||
*/
|
||||
bool
|
||||
hasInheritedFace(const FaceEntry& face);
|
||||
|
||||
bool
|
||||
hasCapture() const;
|
||||
|
||||
/** \brief Determines if the entry has an inherited face with the passed
|
||||
* face ID and its child inherit flag set.
|
||||
* \return{ True, if a matching inherited face is found; otherwise, false. }
|
||||
*/
|
||||
bool
|
||||
hasChildInheritOnFaceId(uint64_t faceId) const;
|
||||
|
||||
/** \brief Returns the face with the lowest cost that has the passed face ID.
|
||||
* \return{ The face with with the lowest cost that has the passed face ID}
|
||||
*/
|
||||
shared_ptr<FaceEntry>
|
||||
getFaceWithLowestCostByFaceId(uint64_t faceId);
|
||||
|
||||
/** \brief Returns the face with the lowest cost that has the passed face ID
|
||||
* and its child inherit flag set.
|
||||
* \return{ The face with with the lowest cost that has the passed face ID
|
||||
* and its child inherit flag set }
|
||||
*/
|
||||
shared_ptr<FaceEntry>
|
||||
getFaceWithLowestCostAndChildInheritByFaceId(uint64_t faceId);
|
||||
|
||||
const_iterator
|
||||
cbegin() const;
|
||||
|
||||
@@ -120,6 +175,14 @@ private:
|
||||
shared_ptr<RibEntry> m_parent;
|
||||
FaceList m_faces;
|
||||
FaceList m_inheritedFaces;
|
||||
|
||||
/** \brief The number of faces on this namespace with the capture flag set.
|
||||
*
|
||||
* This count is used to check if the namespace will block inherited faces.
|
||||
* If the number is greater than zero, a route on the namespace has it's capture
|
||||
* flag set which means the namespace should not inherit any faces.
|
||||
*/
|
||||
uint64_t m_nFacesWithCaptureSet;
|
||||
};
|
||||
|
||||
inline void
|
||||
@@ -158,6 +221,12 @@ RibEntry::getFaces()
|
||||
return m_faces;
|
||||
}
|
||||
|
||||
inline RibEntry::FaceList&
|
||||
RibEntry::getInheritedFaces()
|
||||
{
|
||||
return m_inheritedFaces;
|
||||
}
|
||||
|
||||
inline RibEntry::const_iterator
|
||||
RibEntry::cbegin() const
|
||||
{
|
||||
@@ -182,6 +251,9 @@ RibEntry::end()
|
||||
return m_faces.end();
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const RibEntry& entry);
|
||||
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
+221
-27
@@ -64,6 +64,7 @@ RibManager::RibManager()
|
||||
, m_localhopValidator(m_face)
|
||||
, m_faceMonitor(m_face)
|
||||
, m_isLocalhopEnabled(false)
|
||||
, m_lastTransactionId(0)
|
||||
, m_verbDispatch(COMMAND_VERBS,
|
||||
COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
|
||||
{
|
||||
@@ -225,18 +226,9 @@ RibManager::registerEntry(const shared_ptr<const Interest>& request,
|
||||
|
||||
NFD_LOG_TRACE("register prefix: " << faceEntry);
|
||||
|
||||
/// \todo For right now, just pass the options to fib as is
|
||||
/// without processing flags. Later, options will first be added to
|
||||
/// Rib tree, nrd will generate fib updates based on flags, and
|
||||
/// will then add next hops one by one.
|
||||
m_managedRib.insert(parameters.getName(), faceEntry);
|
||||
m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
|
||||
ControlParameters()
|
||||
.setName(parameters.getName())
|
||||
.setFaceId(faceEntry.faceId)
|
||||
.setCost(faceEntry.cost),
|
||||
bind(&RibManager::onRegSuccess, this, request, parameters, faceEntry),
|
||||
bind(&RibManager::onCommandError, this, _1, _2, request, faceEntry));
|
||||
|
||||
sendUpdatesToFib(request, parameters);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -258,12 +250,9 @@ RibManager::unregisterEntry(const shared_ptr<const Interest>& request,
|
||||
|
||||
NFD_LOG_TRACE("unregister prefix: " << faceEntry);
|
||||
|
||||
m_nfdController.start<ndn::nfd::FibRemoveNextHopCommand>(
|
||||
ControlParameters()
|
||||
.setName(parameters.getName())
|
||||
.setFaceId(faceEntry.faceId),
|
||||
bind(&RibManager::onUnRegSuccess, this, request, parameters, faceEntry),
|
||||
bind(&RibManager::onCommandError, this, _1, _2, request, faceEntry));
|
||||
m_managedRib.erase(parameters.getName(), faceEntry);
|
||||
|
||||
sendUpdatesToFib(request, parameters);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -334,7 +323,6 @@ RibManager::onCommandError(uint32_t code, const std::string& error,
|
||||
}
|
||||
|
||||
sendResponse(request->getName(), response);
|
||||
m_managedRib.erase(request->getName(), faceEntry);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -368,7 +356,53 @@ RibManager::onUnRegSuccess(const shared_ptr<const Interest>& request,
|
||||
NFD_LOG_TRACE("onUnRegSuccess: unregistered " << faceEntry);
|
||||
|
||||
sendResponse(request->getName(), response);
|
||||
m_managedRib.erase(request->getName(), faceEntry);
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::sendSuccessResponse(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters)
|
||||
{
|
||||
if (!static_cast<bool>(request))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ControlResponse response;
|
||||
|
||||
response.setCode(200);
|
||||
response.setText("Success");
|
||||
response.setBody(parameters.wireEncode());
|
||||
|
||||
sendResponse(request->getName(), response);
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::sendErrorResponse(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request)
|
||||
{
|
||||
NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
|
||||
|
||||
if (!static_cast<bool>(request))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ControlResponse response;
|
||||
|
||||
if (code == 404)
|
||||
{
|
||||
response.setCode(code);
|
||||
response.setText(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setCode(533);
|
||||
std::ostringstream os;
|
||||
os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
|
||||
response.setText(os.str());
|
||||
}
|
||||
|
||||
sendResponse(request->getName(), response);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -383,16 +417,87 @@ RibManager::onNrdCommandPrefixAddNextHopError(const Name& name, const std::strin
|
||||
throw Error("Error in setting interest filter (" + name.toUri() + "): " + msg);
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onAddNextHopSuccess(const Name& prefix)
|
||||
bool
|
||||
RibManager::isTransactionComplete(const TransactionId transactionId)
|
||||
{
|
||||
NFD_LOG_DEBUG("Successfully registered " + prefix.toUri() + " with NFD");
|
||||
FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
|
||||
|
||||
if (it != m_pendingFibTransactions.end())
|
||||
{
|
||||
int& updatesLeft = it->second;
|
||||
|
||||
updatesLeft--;
|
||||
|
||||
// All of the updates have been applied successfully
|
||||
if (updatesLeft == 0)
|
||||
{
|
||||
m_pendingFibTransactions.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onAddNextHopError(const Name& name, const std::string& msg)
|
||||
RibManager::invalidateTransaction(const TransactionId transactionId)
|
||||
{
|
||||
throw Error("Error in setting interest filter (" + name.toUri() + "): " + msg);
|
||||
FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
|
||||
|
||||
if (it != m_pendingFibTransactions.end())
|
||||
{
|
||||
m_pendingFibTransactions.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onAddNextHopSuccess(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters,
|
||||
const TransactionId transactionId,
|
||||
const bool shouldSendResponse)
|
||||
{
|
||||
if (isTransactionComplete(transactionId) && shouldSendResponse)
|
||||
{
|
||||
sendSuccessResponse(request, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onAddNextHopError(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request,
|
||||
const TransactionId transactionId, const bool shouldSendResponse)
|
||||
{
|
||||
invalidateTransaction(transactionId);
|
||||
|
||||
if (shouldSendResponse)
|
||||
{
|
||||
sendErrorResponse(code, error, request);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onRemoveNextHopSuccess(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters,
|
||||
const TransactionId transactionId,
|
||||
const bool shouldSendResponse)
|
||||
{
|
||||
if (isTransactionComplete(transactionId) && shouldSendResponse)
|
||||
{
|
||||
sendSuccessResponse(request, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::onRemoveNextHopError(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request,
|
||||
const TransactionId transactionId, const bool shouldSendResponse)
|
||||
{
|
||||
invalidateTransaction(transactionId);
|
||||
|
||||
if (shouldSendResponse)
|
||||
{
|
||||
sendErrorResponse(code, error, request);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -425,9 +530,98 @@ RibManager::onNotification(const FaceEventNotification& notification)
|
||||
{
|
||||
/// \todo A notification can be missed, in this case check Facelist
|
||||
NFD_LOG_TRACE("onNotification: " << notification);
|
||||
if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) { //face destroyed
|
||||
m_managedRib.erase(notification.getFaceId());
|
||||
}
|
||||
if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) //face destroyed
|
||||
{
|
||||
m_managedRib.erase(notification.getFaceId());
|
||||
|
||||
sendUpdatesToFibAfterFaceDestroyEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::sendUpdatesToFib(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters)
|
||||
{
|
||||
const Rib::FibUpdateList& updates = m_managedRib.getFibUpdates();
|
||||
|
||||
// If no updates were generated, consider the operation a success
|
||||
if (updates.empty())
|
||||
{
|
||||
sendSuccessResponse(request, parameters);
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldWaitToRespond = false;
|
||||
|
||||
// An application request should wait for all FIB updates to be applied
|
||||
// successfully before sending a response
|
||||
if (parameters.getOrigin() == ndn::nfd::ROUTE_ORIGIN_APP)
|
||||
{
|
||||
shouldWaitToRespond = true;
|
||||
}
|
||||
else // Respond immediately
|
||||
{
|
||||
sendSuccessResponse(request, parameters);
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("Applying " << updates.size() << " updates to FIB");
|
||||
|
||||
// Assign an ID to this FIB transaction
|
||||
TransactionId currentTransactionId = ++m_lastTransactionId;
|
||||
|
||||
// Add this transaction to the transaction table
|
||||
m_pendingFibTransactions[currentTransactionId] = updates.size();
|
||||
|
||||
for (Rib::FibUpdateList::const_iterator it = updates.begin(); it != updates.end(); ++it)
|
||||
{
|
||||
shared_ptr<const FibUpdate> update(*it);
|
||||
|
||||
if (update->action == FibUpdate::ADD_NEXTHOP)
|
||||
{
|
||||
FaceEntry faceEntry;
|
||||
faceEntry.faceId = update->faceId;
|
||||
faceEntry.cost = update->cost;
|
||||
|
||||
m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
|
||||
ControlParameters()
|
||||
.setName(update->name)
|
||||
.setFaceId(faceEntry.faceId)
|
||||
.setCost(faceEntry.cost),
|
||||
bind(&RibManager::onAddNextHopSuccess, this, request,
|
||||
parameters,
|
||||
currentTransactionId,
|
||||
shouldWaitToRespond),
|
||||
bind(&RibManager::onAddNextHopError, this, _1, _2, request, currentTransactionId,
|
||||
shouldWaitToRespond));
|
||||
}
|
||||
else if (update->action == FibUpdate::REMOVE_NEXTHOP)
|
||||
{
|
||||
FaceEntry faceEntry;
|
||||
faceEntry.faceId = update->faceId;
|
||||
|
||||
m_nfdController.start<ndn::nfd::FibRemoveNextHopCommand>(
|
||||
ControlParameters()
|
||||
.setName(update->name)
|
||||
.setFaceId(faceEntry.faceId),
|
||||
bind(&RibManager::onRemoveNextHopSuccess, this, request,
|
||||
parameters,
|
||||
currentTransactionId,
|
||||
shouldWaitToRespond),
|
||||
bind(&RibManager::onRemoveNextHopError, this, _1, _2, request, currentTransactionId,
|
||||
shouldWaitToRespond));
|
||||
}
|
||||
}
|
||||
|
||||
m_managedRib.clearFibUpdates();
|
||||
}
|
||||
|
||||
void
|
||||
RibManager::sendUpdatesToFibAfterFaceDestroyEvent()
|
||||
{
|
||||
ControlParameters parameters;
|
||||
parameters.setOrigin(ndn::nfd::ROUTE_ORIGIN_STATIC);
|
||||
|
||||
sendUpdatesToFib(shared_ptr<const Interest>(), parameters);
|
||||
}
|
||||
|
||||
} // namespace rib
|
||||
|
||||
+62
-2
@@ -68,6 +68,8 @@ public:
|
||||
setConfigFile(ConfigFile& configFile);
|
||||
|
||||
private:
|
||||
typedef uint32_t TransactionId;
|
||||
|
||||
void
|
||||
onConfig(const ConfigSection& configSection,
|
||||
bool isDryRun,
|
||||
@@ -91,6 +93,14 @@ private:
|
||||
uint32_t code,
|
||||
const std::string& text);
|
||||
|
||||
void
|
||||
sendSuccessResponse(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters);
|
||||
|
||||
void
|
||||
sendErrorResponse(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request);
|
||||
|
||||
void
|
||||
registerEntry(const shared_ptr<const Interest>& request,
|
||||
ControlParameters& parameters);
|
||||
@@ -129,10 +139,26 @@ private:
|
||||
onNrdCommandPrefixAddNextHopError(const Name& name, const std::string& msg);
|
||||
|
||||
void
|
||||
onAddNextHopSuccess(const Name& prefix);
|
||||
onAddNextHopSuccess(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters,
|
||||
const TransactionId transactionId,
|
||||
const bool shouldSendResponse);
|
||||
|
||||
void
|
||||
onAddNextHopError(const Name& name, const std::string& msg);
|
||||
onAddNextHopError(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request,
|
||||
const TransactionId transactionId, const bool shouldSendResponse);
|
||||
|
||||
void
|
||||
onRemoveNextHopSuccess(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters,
|
||||
const TransactionId transactionId,
|
||||
const bool shouldSendResponse);
|
||||
|
||||
void
|
||||
onRemoveNextHopError(uint32_t code, const std::string& error,
|
||||
const shared_ptr<const Interest>& request,
|
||||
const TransactionId transactionId, const bool shouldSendResponse);
|
||||
|
||||
void
|
||||
onControlHeaderSuccess();
|
||||
@@ -150,6 +176,24 @@ private:
|
||||
void
|
||||
onNotification(const FaceEventNotification& notification);
|
||||
|
||||
void
|
||||
sendUpdatesToFib(const shared_ptr<const Interest>& request,
|
||||
const ControlParameters& parameters);
|
||||
|
||||
void
|
||||
sendUpdatesToFibAfterFaceDestroyEvent();
|
||||
|
||||
/** \brief Checks if the transaction has received all of the expected responses
|
||||
* from the FIB.
|
||||
* \return{ True if the transaction with the passed transactionId has applied
|
||||
* all of its FIB updates successfully; otherwise, false }
|
||||
*/
|
||||
bool
|
||||
isTransactionComplete(const TransactionId transactionId);
|
||||
|
||||
void
|
||||
invalidateTransaction(const TransactionId transactionId);
|
||||
|
||||
private:
|
||||
Rib m_managedRib;
|
||||
ndn::Face m_face;
|
||||
@@ -160,6 +204,22 @@ private:
|
||||
FaceMonitor m_faceMonitor;
|
||||
bool m_isLocalhopEnabled;
|
||||
|
||||
/** \brief The last transaction ID for FIB update response messages.
|
||||
* Each group of FIB updates applied to the FIB is assigned an incrementing
|
||||
* ID that is used to track the number of successfully applied updates.
|
||||
*/
|
||||
TransactionId m_lastTransactionId;
|
||||
|
||||
/// table of FIB update transactions => count of pending FIB updates
|
||||
typedef std::map<TransactionId, int> FibTransactionTable;
|
||||
|
||||
/** \brief Table used to track the number of FIB updates that have not yet received
|
||||
* a response from the FIB.
|
||||
* The table maps a transaction ID to the number of updates remaining for that
|
||||
* specific transaction.
|
||||
*/
|
||||
FibTransactionTable m_pendingFibTransactions;
|
||||
|
||||
typedef function<void(RibManager*,
|
||||
const shared_ptr<const Interest>& request,
|
||||
ControlParameters& parameters)> VerbProcessor;
|
||||
|
||||
+544
-4
@@ -28,6 +28,36 @@
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
|
||||
static inline bool
|
||||
sortFace(const FaceEntry& entry1, const FaceEntry& entry2)
|
||||
{
|
||||
return entry1.faceId < entry2.faceId;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
isChildInheritFlagSet(uint64_t flags)
|
||||
{
|
||||
return flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
isCaptureFlagSet(uint64_t flags)
|
||||
{
|
||||
return flags & ndn::nfd::ROUTE_FLAG_CAPTURE;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
isAnyFlagSet(uint64_t flags)
|
||||
{
|
||||
return isChildInheritFlagSet(flags) || isCaptureFlagSet(flags);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
areBothFlagsSet(uint64_t flags)
|
||||
{
|
||||
return isChildInheritFlagSet(flags) && isCaptureFlagSet(flags);
|
||||
}
|
||||
|
||||
Rib::Rib()
|
||||
: m_nItems(0)
|
||||
{
|
||||
@@ -66,7 +96,6 @@ Rib::find(const Name& prefix, const FaceEntry& face) const
|
||||
return shared_ptr<FaceEntry>();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Rib::insert(const Name& prefix, const FaceEntry& face)
|
||||
{
|
||||
@@ -83,19 +112,32 @@ Rib::insert(const Name& prefix, const FaceEntry& face)
|
||||
|
||||
if (faceIt == entry->end())
|
||||
{
|
||||
// Will the new face change the namespace's capture flag?
|
||||
bool captureWasTurnedOn = (entry->hasCapture() == false && isCaptureFlagSet(face.flags));
|
||||
|
||||
// New face
|
||||
entry->insertFace(face);
|
||||
m_nItems++;
|
||||
|
||||
// Register with face lookup table
|
||||
m_faceMap[face.faceId].push_back(entry);
|
||||
|
||||
createFibUpdatesForNewFaceEntry(*entry, face, captureWasTurnedOn);
|
||||
}
|
||||
else
|
||||
else // Entry exists, update fields
|
||||
{
|
||||
// Entry exists, update other fields
|
||||
// Save flags for update processing
|
||||
uint64_t previousFlags = faceIt->flags;
|
||||
|
||||
// If the entry's cost didn't change and child inherit is not set,
|
||||
// no need to traverse subtree.
|
||||
uint64_t previousCost = faceIt->cost;
|
||||
|
||||
faceIt->flags = face.flags;
|
||||
faceIt->cost = face.cost;
|
||||
faceIt->expires = face.expires;
|
||||
|
||||
createFibUpdatesForUpdatedEntry(*entry, face, previousFlags, previousCost);
|
||||
}
|
||||
}
|
||||
else // New name prefix
|
||||
@@ -136,6 +178,8 @@ Rib::insert(const Name& prefix, const FaceEntry& face)
|
||||
|
||||
// Register with face lookup table
|
||||
m_faceMap[face.faceId].push_back(entry);
|
||||
|
||||
createFibUpdatesForNewRibEntry(*entry, face);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,15 +194,39 @@ Rib::erase(const Name& prefix, const FaceEntry& face)
|
||||
{
|
||||
shared_ptr<RibEntry> entry(ribIt->second);
|
||||
|
||||
if (entry->eraseFace(face))
|
||||
const bool hadCapture = entry->hasCapture();
|
||||
|
||||
// Need to copy face to do FIB updates with correct cost and flags since nfdc does not
|
||||
// pass flags or cost
|
||||
RibEntry::iterator faceIt = entry->findFace(face);
|
||||
FaceEntry faceToErase = *faceIt;
|
||||
faceToErase.flags = faceIt->flags;
|
||||
faceToErase.cost = faceIt->cost;
|
||||
|
||||
if (faceIt != entry->end())
|
||||
{
|
||||
entry->eraseFace(faceIt);
|
||||
m_nItems--;
|
||||
|
||||
const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
|
||||
|
||||
createFibUpdatesForErasedFaceEntry(*entry, faceToErase, captureWasTurnedOff);
|
||||
|
||||
// If this RibEntry no longer has this faceId, unregister from face lookup table
|
||||
if (!entry->hasFaceId(face.faceId))
|
||||
{
|
||||
m_faceMap[face.faceId].remove(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The RibEntry still has the face ID; need to update FIB
|
||||
// with lowest cost for the same face instead of removing the face from the FIB
|
||||
shared_ptr<FaceEntry> lowCostFace = entry->getFaceWithLowestCostByFaceId(face.faceId);
|
||||
|
||||
BOOST_ASSERT(static_cast<bool>(lowCostFace));
|
||||
|
||||
createFibUpdatesForNewFaceEntry(*entry, *lowCostFace, false);
|
||||
}
|
||||
|
||||
// If a RibEntry's facelist is empty, remove it from the tree
|
||||
if (entry->getFaces().size() == 0)
|
||||
@@ -187,12 +255,19 @@ Rib::erase(const uint64_t faceId)
|
||||
{
|
||||
shared_ptr<RibEntry> entry = *entryIt;
|
||||
|
||||
const bool hadCapture = entry->hasCapture();
|
||||
|
||||
// Find the faces in the entry
|
||||
for (RibEntry::iterator faceIt = entry->begin(); faceIt != entry->end(); ++faceIt)
|
||||
{
|
||||
if (faceIt->faceId == faceId)
|
||||
{
|
||||
FaceEntry copy = *faceIt;
|
||||
|
||||
faceIt = entry->eraseFace(faceIt);
|
||||
|
||||
const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
|
||||
createFibUpdatesForErasedFaceEntry(*entry, copy, captureWasTurnedOff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +339,9 @@ Rib::eraseEntry(RibTable::iterator it)
|
||||
|
||||
shared_ptr<RibEntry> entry(it->second);
|
||||
|
||||
// Remove inherited routes from namespace
|
||||
createFibUpdatesForErasedRibEntry(*entry);
|
||||
|
||||
shared_ptr<RibEntry> parent = entry->getParent();
|
||||
|
||||
// Remove self from parent's children
|
||||
@@ -295,6 +373,468 @@ Rib::eraseEntry(RibTable::iterator it)
|
||||
return nextIt;
|
||||
}
|
||||
|
||||
bool
|
||||
compareFibUpdates(const shared_ptr<const FibUpdate> lhs, const shared_ptr<const FibUpdate> rhs)
|
||||
{
|
||||
return ((lhs->name == rhs->name) &&
|
||||
(lhs->faceId == rhs->faceId));
|
||||
}
|
||||
|
||||
void
|
||||
Rib::insertFibUpdate(shared_ptr<FibUpdate> update)
|
||||
{
|
||||
// If an update with the same name and face already exists,
|
||||
// replace it
|
||||
FibUpdateList::iterator it = std::find_if(m_fibUpdateList.begin(), m_fibUpdateList.end(),
|
||||
bind(&compareFibUpdates, _1, update));
|
||||
|
||||
if (it != m_fibUpdateList.end())
|
||||
{
|
||||
// Get rid of the const to alter the action, prevents copying or removal and
|
||||
// insertion
|
||||
FibUpdate& entry = const_cast<FibUpdate&>(*(*it));
|
||||
entry.action = update->action;
|
||||
entry.cost = update->cost;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fibUpdateList.push_back(update);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::createFibUpdatesForNewRibEntry(RibEntry& entry, const FaceEntry& face)
|
||||
{
|
||||
// Create FIB update for new entry
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
|
||||
|
||||
// No flags are set
|
||||
if (!isAnyFlagSet(face.flags))
|
||||
{
|
||||
// Add ancestor faces to self
|
||||
addInheritedFacesToEntry(entry, getAncestorFaces(entry));
|
||||
}
|
||||
else if (areBothFlagsSet(face.flags))
|
||||
{
|
||||
// Add face to children
|
||||
FaceSet facesToAdd;
|
||||
facesToAdd.insert(face);
|
||||
|
||||
// Remove faces blocked by capture and add self to children
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, getAncestorFaces(entry));
|
||||
}
|
||||
else if (isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
FaceSet ancestorFaces = getAncestorFaces(entry);
|
||||
|
||||
// Add ancestor faces to self
|
||||
addInheritedFacesToEntry(entry, ancestorFaces);
|
||||
|
||||
// If there is an ancestor face which is the same as the new face, replace it
|
||||
// with the new face
|
||||
FaceSet::iterator it = ancestorFaces.find(face);
|
||||
|
||||
// There is a face that needs to be overwritten, erase and then replace
|
||||
if (it != ancestorFaces.end())
|
||||
{
|
||||
ancestorFaces.erase(it);
|
||||
}
|
||||
|
||||
// Add new face to ancestor list so it can be added to children
|
||||
ancestorFaces.insert(face);
|
||||
|
||||
// Add ancestor faces to children
|
||||
modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
|
||||
}
|
||||
else if (isCaptureFlagSet(face.flags))
|
||||
{
|
||||
// Remove faces blocked by capture
|
||||
modifyChildrensInheritedFaces(entry, FaceSet(), getAncestorFaces(entry));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::createFibUpdatesForNewFaceEntry(RibEntry& entry, const FaceEntry& face,
|
||||
bool captureWasTurnedOn)
|
||||
{
|
||||
// Only update if the new face has a lower cost than a previously installed face
|
||||
shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);
|
||||
|
||||
FaceSet facesToAdd;
|
||||
if (isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
// Add to children if this new face doesn't override a previous lower cost, or
|
||||
// add to children if this new is lower cost than a previous face.
|
||||
// Less than equal, since entry may find this face
|
||||
if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
|
||||
{
|
||||
// Add self to children
|
||||
facesToAdd.insert(face);
|
||||
}
|
||||
}
|
||||
|
||||
FaceSet facesToRemove;
|
||||
if (captureWasTurnedOn)
|
||||
{
|
||||
// Capture flag on
|
||||
facesToRemove = getAncestorFaces(entry);
|
||||
|
||||
// Remove ancestor faces from self
|
||||
removeInheritedFacesFromEntry(entry, facesToRemove);
|
||||
}
|
||||
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
|
||||
|
||||
// If another face with same faceId and lower cost, don't update.
|
||||
// Must be done last so that add updates replace removal updates
|
||||
// Create FIB update for new entry
|
||||
if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
|
||||
{
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::createFibUpdatesForUpdatedEntry(RibEntry& entry, const FaceEntry& face,
|
||||
const uint64_t previousFlags, const uint64_t previousCost)
|
||||
{
|
||||
const bool costDidChange = (face.cost != previousCost);
|
||||
|
||||
// Look for an installed face with the lowest cost and child inherit set
|
||||
shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);
|
||||
|
||||
// No flags changed and cost didn't change, no change in FIB
|
||||
if (face.flags == previousFlags && !costDidChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Cost changed so create update for the entry itself
|
||||
if (costDidChange)
|
||||
{
|
||||
// Create update if this face's cost is lower than other faces
|
||||
if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
|
||||
{
|
||||
// Create FIB update for the updated entry
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
|
||||
}
|
||||
else if (previousCost < entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
|
||||
{
|
||||
// Create update if this face used to be the lowest face but is no longer
|
||||
// the lowest cost face.
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevFace->faceId,
|
||||
prevFace->cost));
|
||||
}
|
||||
|
||||
// If another face with same faceId and lower cost and ChildInherit exists,
|
||||
// don't update children.
|
||||
if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
|
||||
{
|
||||
// If no flags changed but child inheritance is set, need to update children
|
||||
// with new cost
|
||||
if ((face.flags == previousFlags) && isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
// Add self to children
|
||||
FaceSet facesToAdd;
|
||||
facesToAdd.insert(face);
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Child inherit was turned on
|
||||
if (!isChildInheritFlagSet(previousFlags) && isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
// If another face with same faceId and lower cost and ChildInherit exists,
|
||||
// don't update children.
|
||||
if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
|
||||
{
|
||||
// Add self to children
|
||||
FaceSet facesToAdd;
|
||||
facesToAdd.insert(face);
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
|
||||
}
|
||||
|
||||
} // Child inherit was turned off
|
||||
else if (isChildInheritFlagSet(previousFlags) && !isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
// Remove self from children
|
||||
FaceSet facesToRemove;
|
||||
facesToRemove.insert(face);
|
||||
|
||||
FaceSet facesToAdd;
|
||||
// If another face with same faceId and ChildInherit exists, update children with this face.
|
||||
if (static_cast<bool>(prevFace))
|
||||
{
|
||||
facesToAdd.insert(*prevFace);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for an ancestor that was blocked previously
|
||||
const FaceSet ancestorFaces = getAncestorFaces(entry);
|
||||
FaceSet::iterator it = ancestorFaces.find(face);
|
||||
|
||||
// If an ancestor is found, add it to children
|
||||
if (it != ancestorFaces.end())
|
||||
{
|
||||
facesToAdd.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
|
||||
}
|
||||
|
||||
// Capture was turned on
|
||||
if (!isCaptureFlagSet(previousFlags) && isCaptureFlagSet(face.flags))
|
||||
{
|
||||
FaceSet ancestorFaces = getAncestorFaces(entry);
|
||||
|
||||
// Remove ancestor faces from self
|
||||
removeInheritedFacesFromEntry(entry, ancestorFaces);
|
||||
|
||||
// Remove ancestor faces from children
|
||||
modifyChildrensInheritedFaces(entry, FaceSet(), ancestorFaces);
|
||||
} // Capture was turned off
|
||||
else if (isCaptureFlagSet(previousFlags) && !isCaptureFlagSet(face.flags))
|
||||
{
|
||||
FaceSet ancestorFaces = getAncestorFaces(entry);
|
||||
|
||||
// Add ancestor faces to self
|
||||
addInheritedFacesToEntry(entry, ancestorFaces);
|
||||
|
||||
// Add ancestor faces to children
|
||||
modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::createFibUpdatesForErasedFaceEntry(RibEntry& entry, const FaceEntry& face,
|
||||
const bool captureWasTurnedOff)
|
||||
{
|
||||
insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), face.faceId));
|
||||
|
||||
if (areBothFlagsSet(face.flags))
|
||||
{
|
||||
// Remove self from children
|
||||
FaceSet facesToRemove;
|
||||
facesToRemove.insert(face);
|
||||
|
||||
// If capture is turned off for the route, need to add ancestors
|
||||
// to self and children
|
||||
FaceSet facesToAdd;
|
||||
if (captureWasTurnedOff)
|
||||
{
|
||||
// Look for an ancestors that were blocked previously
|
||||
facesToAdd = getAncestorFaces(entry);
|
||||
|
||||
// Add ancestor faces to self
|
||||
addInheritedFacesToEntry(entry, facesToAdd);
|
||||
}
|
||||
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
|
||||
}
|
||||
else if (isChildInheritFlagSet(face.flags))
|
||||
{
|
||||
// If not blocked by capture, add inherited routes to children
|
||||
FaceSet facesToAdd;
|
||||
if (!entry.hasCapture())
|
||||
{
|
||||
facesToAdd = getAncestorFaces(entry);
|
||||
}
|
||||
|
||||
FaceSet facesToRemove;
|
||||
facesToRemove.insert(face);
|
||||
|
||||
// Add ancestor faces to children
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
|
||||
}
|
||||
else if (isCaptureFlagSet(face.flags))
|
||||
{
|
||||
// If capture is turned off for the route, need to add ancestors
|
||||
// to self and children
|
||||
FaceSet facesToAdd;
|
||||
if (captureWasTurnedOff)
|
||||
{
|
||||
// Look for an ancestors that were blocked previously
|
||||
facesToAdd = getAncestorFaces(entry);
|
||||
|
||||
// Add ancestor faces to self
|
||||
addInheritedFacesToEntry(entry, facesToAdd);
|
||||
}
|
||||
|
||||
modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
|
||||
}
|
||||
|
||||
// Need to check if the removed face was blocking an inherited route
|
||||
FaceSet ancestorFaces = getAncestorFaces(entry);
|
||||
|
||||
if (!entry.hasCapture())
|
||||
{
|
||||
// If there is an ancestor face which is the same as the erased face, add that face
|
||||
// to the current entry
|
||||
FaceSet::iterator it = ancestorFaces.find(face);
|
||||
|
||||
if (it != ancestorFaces.end())
|
||||
{
|
||||
entry.addInheritedFace(*it);
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::createFibUpdatesForErasedRibEntry(RibEntry& entry)
|
||||
{
|
||||
for (RibEntry::FaceList::iterator it = entry.getInheritedFaces().begin();
|
||||
it != entry.getInheritedFaces().end(); ++it)
|
||||
{
|
||||
insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
|
||||
}
|
||||
}
|
||||
|
||||
Rib::FaceSet
|
||||
Rib::getAncestorFaces(const RibEntry& entry) const
|
||||
{
|
||||
FaceSet ancestorFaces(&sortFace);
|
||||
|
||||
shared_ptr<RibEntry> parent = entry.getParent();
|
||||
|
||||
while (static_cast<bool>(parent))
|
||||
{
|
||||
for (RibEntry::iterator it = parent->getFaces().begin();
|
||||
it != parent->getFaces().end(); ++it)
|
||||
{
|
||||
if (isChildInheritFlagSet(it->flags))
|
||||
{
|
||||
ancestorFaces.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent->hasCapture())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
parent = parent->getParent();
|
||||
}
|
||||
|
||||
return ancestorFaces;
|
||||
}
|
||||
|
||||
void
|
||||
Rib::addInheritedFacesToEntry(RibEntry& entry, const Rib::FaceSet& facesToAdd)
|
||||
{
|
||||
for (FaceSet::const_iterator it = facesToAdd.begin(); it != facesToAdd.end(); ++it)
|
||||
{
|
||||
// Don't add an ancestor faceId if the namespace has an entry for that faceId
|
||||
if (!entry.hasFaceId(it->faceId))
|
||||
{
|
||||
entry.addInheritedFace(*it);
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::removeInheritedFacesFromEntry(RibEntry& entry, const Rib::FaceSet& facesToRemove)
|
||||
{
|
||||
for (FaceSet::const_iterator it = facesToRemove.begin(); it != facesToRemove.end(); ++it)
|
||||
{
|
||||
// Only remove if the face has been inherited
|
||||
if (entry.hasInheritedFace(*it))
|
||||
{
|
||||
entry.removeInheritedFace(*it);
|
||||
insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::modifyChildrensInheritedFaces(RibEntry& entry, const Rib::FaceSet& facesToAdd,
|
||||
const Rib::FaceSet& facesToRemove)
|
||||
{
|
||||
RibEntryList children = entry.getChildren();
|
||||
|
||||
for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
|
||||
{
|
||||
traverseSubTree(*(*child), facesToAdd, facesToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Rib::traverseSubTree(RibEntry& entry, Rib::FaceSet facesToAdd,
|
||||
Rib::FaceSet facesToRemove)
|
||||
{
|
||||
// If a route on the namespace has the capture flag set, ignore self and children
|
||||
if (entry.hasCapture())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove inherited faces from current namespace
|
||||
for (Rib::FaceSet::const_iterator removeIt = facesToRemove.begin();
|
||||
removeIt != facesToRemove.end(); )
|
||||
{
|
||||
// If a route on the namespace has the same face and child inheritance set, ignore this face
|
||||
if (entry.hasChildInheritOnFaceId(removeIt->faceId))
|
||||
{
|
||||
facesToRemove.erase(removeIt++);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only remove face if it removes an existing inherited route
|
||||
if (entry.hasInheritedFace(*removeIt))
|
||||
{
|
||||
entry.removeInheritedFace(*removeIt);
|
||||
insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
|
||||
}
|
||||
|
||||
++removeIt;
|
||||
}
|
||||
|
||||
// Add inherited faces to current namespace
|
||||
for (Rib::FaceSet::const_iterator addIt = facesToAdd.begin();
|
||||
addIt != facesToAdd.end(); )
|
||||
{
|
||||
// If a route on the namespace has the same face and child inherit set, ignore this face
|
||||
if (entry.hasChildInheritOnFaceId(addIt->faceId))
|
||||
{
|
||||
facesToAdd.erase(addIt++);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only add face if it does not override an existing route
|
||||
if (!entry.hasFaceId(addIt->faceId))
|
||||
{
|
||||
RibEntry::FaceList::iterator faceIt = entry.findInheritedFace(*addIt);
|
||||
|
||||
// If the entry already has the inherited face, just update the face
|
||||
if (faceIt != entry.getInheritedFaces().end())
|
||||
{
|
||||
faceIt->cost = addIt->cost;
|
||||
}
|
||||
else // Otherwise, this is a newly inherited face
|
||||
{
|
||||
entry.addInheritedFace(*addIt);
|
||||
}
|
||||
|
||||
insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
|
||||
}
|
||||
|
||||
++addIt;
|
||||
}
|
||||
|
||||
Rib::RibEntryList children = entry.getChildren();
|
||||
|
||||
// Apply face operations to current namespace's children
|
||||
for (Rib::RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
|
||||
{
|
||||
traverseSubTree(*(*child), facesToAdd, facesToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Rib& rib)
|
||||
{
|
||||
|
||||
+63
-6
@@ -26,6 +26,8 @@
|
||||
#ifndef NFD_RIB_RIB_HPP
|
||||
#define NFD_RIB_RIB_HPP
|
||||
|
||||
#include "rib-entry.hpp"
|
||||
#include "fib-update.hpp"
|
||||
#include "common.hpp"
|
||||
#include "rib-entry.hpp"
|
||||
#include <ndn-cxx/management/nfd-control-command.hpp>
|
||||
@@ -42,6 +44,9 @@ public:
|
||||
typedef std::map<Name, shared_ptr<RibEntry> > RibTable;
|
||||
typedef RibTable::const_iterator const_iterator;
|
||||
typedef std::map<uint64_t, std::list<shared_ptr<RibEntry> > > FaceLookupTable;
|
||||
typedef bool (*FaceComparePredicate)(const FaceEntry&, const FaceEntry&);
|
||||
typedef std::set<FaceEntry, FaceComparePredicate> FaceSet;
|
||||
typedef std::list<shared_ptr<const FibUpdate> > FibUpdateList;
|
||||
|
||||
Rib();
|
||||
|
||||
@@ -74,7 +79,6 @@ public:
|
||||
bool
|
||||
empty() const;
|
||||
|
||||
|
||||
shared_ptr<RibEntry>
|
||||
findParent(const Name& prefix) const;
|
||||
|
||||
@@ -84,15 +88,62 @@ public:
|
||||
std::list<shared_ptr<RibEntry> >
|
||||
findDescendants(const Name& prefix) const;
|
||||
|
||||
const std::list<shared_ptr<const FibUpdate> >&
|
||||
getFibUpdates() const;
|
||||
|
||||
void
|
||||
clearFibUpdates();
|
||||
|
||||
private:
|
||||
RibTable::iterator
|
||||
eraseEntry(RibTable::iterator it);
|
||||
|
||||
void
|
||||
eraseEntry(const Name& name);
|
||||
insertFibUpdate(shared_ptr<FibUpdate> update);
|
||||
|
||||
void
|
||||
createFibUpdatesForNewRibEntry(RibEntry& entry, const FaceEntry& face);
|
||||
|
||||
void
|
||||
createFibUpdatesForNewFaceEntry(RibEntry& entry, const FaceEntry& face,
|
||||
const bool captureWasTurnedOn);
|
||||
|
||||
void
|
||||
createFibUpdatesForUpdatedEntry(RibEntry& entry, const FaceEntry& face,
|
||||
const uint64_t previousFlags, const uint64_t previousCost);
|
||||
void
|
||||
createFibUpdatesForErasedFaceEntry(RibEntry& entry, const FaceEntry& face,
|
||||
const bool captureWasTurnedOff);
|
||||
|
||||
void
|
||||
createFibUpdatesForErasedRibEntry(RibEntry& entry);
|
||||
|
||||
FaceSet
|
||||
getAncestorFaces(const RibEntry& entry) const;
|
||||
|
||||
void
|
||||
modifyChildrensInheritedFaces(RibEntry& entry, const Rib::FaceSet& facesToAdd,
|
||||
const Rib::FaceSet& facesToRemove);
|
||||
|
||||
void
|
||||
traverseSubTree(RibEntry& entry, Rib::FaceSet facesToAdd,
|
||||
Rib::FaceSet facesToRemove);
|
||||
|
||||
/** \brief Adds passed faces to the entry's inherited faces list
|
||||
*/
|
||||
void
|
||||
addInheritedFacesToEntry(RibEntry& entry, const Rib::FaceSet& facesToAdd);
|
||||
|
||||
/** \brief Removes passed faces from the entry's inherited faces list
|
||||
*/
|
||||
void
|
||||
removeInheritedFacesFromEntry(RibEntry& entry, const Rib::FaceSet& facesToRemove);
|
||||
|
||||
private:
|
||||
RibTable m_rib;
|
||||
FaceLookupTable m_faceMap;
|
||||
FibUpdateList m_fibUpdateList;
|
||||
|
||||
size_t m_nItems;
|
||||
};
|
||||
|
||||
@@ -120,11 +171,17 @@ Rib::empty() const
|
||||
return m_rib.empty();
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceEntry& entry);
|
||||
inline const Rib::FibUpdateList&
|
||||
Rib::getFibUpdates() const
|
||||
{
|
||||
return m_fibUpdateList;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const RibEntry& entry);
|
||||
inline void
|
||||
Rib::clearFibUpdates()
|
||||
{
|
||||
m_fibUpdateList.clear();
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Rib& rib);
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
namespace tests {
|
||||
|
||||
inline FaceEntry
|
||||
createFaceEntry(uint64_t faceId, uint64_t origin, uint64_t cost, uint64_t flags)
|
||||
{
|
||||
FaceEntry temp;
|
||||
temp.faceId = faceId;
|
||||
temp.origin = origin;
|
||||
temp.cost = cost;
|
||||
temp.flags = flags;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline bool
|
||||
compareNameFaceIdCostAction(const shared_ptr<const FibUpdate>& lhs,
|
||||
const shared_ptr<const FibUpdate>& rhs)
|
||||
{
|
||||
if (lhs->name < rhs->name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (lhs->name == rhs->name)
|
||||
{
|
||||
if (lhs->faceId < rhs->faceId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (lhs->faceId == rhs->faceId)
|
||||
{
|
||||
if (lhs->cost < rhs->cost)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (lhs->cost == rhs->cost)
|
||||
{
|
||||
return lhs->action < rhs->action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
class FibUpdatesFixture : public nfd::tests::BaseFixture
|
||||
{
|
||||
public:
|
||||
void
|
||||
insertFaceEntry(const Name& name, uint64_t faceId, uint64_t origin, uint64_t cost, uint64_t flags)
|
||||
{
|
||||
rib::FaceEntry faceEntry;
|
||||
faceEntry.faceId = faceId;
|
||||
faceEntry.origin = origin;
|
||||
faceEntry.cost = cost;
|
||||
faceEntry.flags = flags;
|
||||
|
||||
rib.insert(name, faceEntry);
|
||||
}
|
||||
|
||||
void
|
||||
eraseFaceEntry(const Name& name, uint64_t faceId, uint64_t origin)
|
||||
{
|
||||
rib::FaceEntry faceEntry;
|
||||
faceEntry.faceId = faceId;
|
||||
faceEntry.origin = origin;
|
||||
|
||||
rib.erase(name, faceEntry);
|
||||
}
|
||||
|
||||
|
||||
Rib::FibUpdateList
|
||||
getSortedFibUpdates()
|
||||
{
|
||||
Rib::FibUpdateList updates = rib.getFibUpdates();
|
||||
updates.sort(&compareNameFaceIdCostAction);
|
||||
return updates;
|
||||
}
|
||||
|
||||
public:
|
||||
rib::Rib rib;
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,396 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
#include "rib/rib.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "fib-updates-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(FibUpdates, FibUpdatesFixture)
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(EraseFace)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(WithInheritedFace_Root)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 2, 0, 75, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to remove face 1 from /
|
||||
eraseFaceEntry("/", 1, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(WithInheritedFace)
|
||||
{
|
||||
insertFaceEntry("/a", 5, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 5, 255, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 20, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 5, 0);
|
||||
|
||||
// /a should have face 5 with cost 10; /a/b should have face 3 with cost 5 and
|
||||
// face 5 with cost 10
|
||||
eraseFaceEntry("/a", 5, 255);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to remove face 3 from /a/b and one to remove inherited face.
|
||||
eraseFaceEntry("/a/b", 3, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 3);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MultipleFaces)
|
||||
{
|
||||
insertFaceEntry("/a", 5, 0, 10, 0);
|
||||
insertFaceEntry("/a", 5, 255, 5, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to update cost to 10 for /a
|
||||
eraseFaceEntry("/a", 5, 255);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoFlags_NoCaptureChange_NoCaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to update cost for /a
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MakeRibEmpty)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to remove face from /
|
||||
eraseFaceEntry("/", 1, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoFlags_NoCaptureChange_CaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to remove face from /a
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BothFlags_NoCaptureChange_CaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, (ndn::nfd::ROUTE_FLAG_CHILD_INHERIT |
|
||||
ndn::nfd::ROUTE_FLAG_CAPTURE));
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to remove face1 from /a and
|
||||
// 1 to remove face1 to /a/b
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BothFlags_CaptureChange_NoCaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, (ndn::nfd::ROUTE_FLAG_CHILD_INHERIT |
|
||||
ndn::nfd::ROUTE_FLAG_CAPTURE));
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to add face1 to /a and
|
||||
// 1 to add face1 to /a/b
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChildInherit_NoCaptureChange_NoCaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 2 to add face1 to /a and /a/b
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChildInherit_NoCaptureChange_CaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 2 to remove face 1 from /a and /a/b
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Capture_CaptureChange_NoCaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to update cost on /a and
|
||||
// 1 to add face1 to /a/b
|
||||
eraseFaceEntry("/a", 1 ,128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Capture_NoCaptureChange_CaptureOnRoute)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 updates: 1 to remove face from /a
|
||||
eraseFaceEntry("/a", 1, 128);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(EraseFaceById)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 100, 0);
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 4 updates: 4 to remove face ID 1 from /, /a, /a/b, and /a/c
|
||||
rib.erase(1);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 4);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/c");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // EraseFace
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // FibUpdates
|
||||
|
||||
} // namespace tests
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,272 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
#include "rib/rib.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "fib-updates-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(FibUpdates, FibUpdatesFixture)
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(NewFace)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Basic)
|
||||
{
|
||||
// should generate 1 update
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = rib.getFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
// Clear any updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// should generate 2 updates
|
||||
insertFaceEntry("/a", 2, 0, 50, 0);
|
||||
|
||||
updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// should generate 2 updates
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
|
||||
updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 3);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UpdateOnLowerCostNoChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, 0);
|
||||
|
||||
// Clear any updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 0 updates
|
||||
insertFaceEntry("/", 1, 128, 75, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(rib.getFibUpdates().size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UpdateOnLowerCostOnly)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: to update cost for face 1 on / and /a
|
||||
insertFaceEntry("/", 1, 0, 25, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 25);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 25);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 0 updates
|
||||
insertFaceEntry("/", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
BOOST_CHECK_EQUAL(rib.getFibUpdates().size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoCaptureChangeWithoutChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 1 update: 1 to add face 5 to /a
|
||||
insertFaceEntry("/a", 5, 128, 50, 0);
|
||||
|
||||
const Rib::FibUpdateList& updates = rib.getFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoCaptureChangeWithChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: one for the inserted face and
|
||||
// one to add face to /a/b
|
||||
insertFaceEntry("/a", 4, 128, 5, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 4);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 4);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 5);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CaptureTurnedOnWithoutChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 3 updates:
|
||||
// - one for the inserted face for /a and
|
||||
// - two to remove face1 from /a/b and /a/c
|
||||
insertFaceEntry("/a", 1, 128, 50, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 3);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/c");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CaptureTurnedOnWithChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates:
|
||||
// - one for the inserted face for /a and
|
||||
// - one to update /a/b with the new cost
|
||||
insertFaceEntry("/a", 1, 128, 50, (ndn::nfd::ROUTE_FLAG_CAPTURE |
|
||||
ndn::nfd::ROUTE_FLAG_CHILD_INHERIT));
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 3);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // NewFace
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // FibUpdates
|
||||
|
||||
} // namespace tests
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,202 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
#include "rib/rib.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "fib-updates-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(FibUpdates, FibUpdatesFixture)
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(NewNamespace)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoFlags)
|
||||
{
|
||||
// No flags, empty RIB, should generate 1 update for the inserted face
|
||||
insertFaceEntry("/a/b", 1, 0, 10, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
// Reset RIB
|
||||
eraseFaceEntry("/a/b", 1, 0);
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Parent with child inherit flag
|
||||
insertFaceEntry("/a", 2, 0, 70, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 3, 0, 30, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 3 updates, 1 for the inserted face and 2 from inheritance
|
||||
insertFaceEntry("/a/b", 1, 0, 10, 0);
|
||||
|
||||
updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 3);
|
||||
|
||||
update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 70);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 3);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 30);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BothFlags)
|
||||
{
|
||||
// Empty RIB, should generate 1 update for the inserted face
|
||||
insertFaceEntry("/a", 1, 0, 10, (ndn::nfd::ROUTE_FLAG_CHILD_INHERIT |
|
||||
ndn::nfd::ROUTE_FLAG_CAPTURE));
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
// Reset RIB
|
||||
eraseFaceEntry("/a", 1, 0);
|
||||
rib.clearFibUpdates();
|
||||
|
||||
insertFaceEntry("/", 2, 0, 70, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 30, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 3 updates, 1 for the inserted face, 1 to add the face to the child,
|
||||
// and 1 to remove the previously inherited entry
|
||||
insertFaceEntry("/a", 1, 0, 10, (ndn::nfd::ROUTE_FLAG_CHILD_INHERIT |
|
||||
ndn::nfd::ROUTE_FLAG_CAPTURE));
|
||||
|
||||
updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 3);
|
||||
|
||||
update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 3, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 for the inserted face and 1 to add the face to "/a/b"
|
||||
insertFaceEntry("/a", 1, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Capture)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 3, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 for the inserted face and
|
||||
// 1 to remove inherited face from "/a/b"
|
||||
insertFaceEntry("/a", 1, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // NewNamespace
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // FibUpdates
|
||||
|
||||
} // namespace tests
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,266 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, 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/>.
|
||||
*/
|
||||
|
||||
#include "rib/rib.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "fib-updates-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(FibUpdates, FibUpdatesFixture)
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(UpdateFace)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TurnOffChildInheritLowerCost)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/", 1, 128, 25, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to update the cost of / face 1 to 50 and
|
||||
// 1 to update the cost of /a face 1 to 50
|
||||
insertFaceEntry("/", 1, 128, 75, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UpdateOnLowerCostOnly)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/", 1, 128, 100, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 0 updates
|
||||
insertFaceEntry("/", 1, 128, 75, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates
|
||||
insertFaceEntry("/", 1, 128, 25, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 25);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 25);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NoChangeInCost)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 100, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 0 updates
|
||||
insertFaceEntry("/a", 2, 0, 100, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChangeCost)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 100, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Should generate 2 updates: 1 to add face2 with new cost to /a and
|
||||
// 1 to add face2 with new cost to /a/b
|
||||
insertFaceEntry("/a", 2, 0, 300, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 300);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 300);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TurnOnChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 4, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Turn on child inherit flag for the entry in /a
|
||||
// Should generate 1 updates: 1 to add face to /a/b
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 2);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 10);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TurnOffChildInherit)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 1, 0, 100, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a/b", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 25, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Turn off child inherit flag for the entry in /a
|
||||
// Should generate 1 update: 1 to add face1 to /a/b
|
||||
insertFaceEntry("/a", 1, 0, 100, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 1);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TurnOnCapture)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 10, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Turn on capture flag for the entry in /a
|
||||
// Should generate 2 updates: 1 to remove face1 from /a and
|
||||
// 1 to remove face1 from /a/b
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::REMOVE_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TurnOffCapture)
|
||||
{
|
||||
insertFaceEntry("/", 1, 0, 50, ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
|
||||
insertFaceEntry("/a", 2, 0, 10, ndn::nfd::ROUTE_FLAG_CAPTURE);
|
||||
insertFaceEntry("/a/b", 3, 0, 10, 0);
|
||||
insertFaceEntry("/a/c", 1, 0, 10, 0);
|
||||
|
||||
// Clear updates generated from previous insertions
|
||||
rib.clearFibUpdates();
|
||||
|
||||
// Turn off capture flag for the entry in /a
|
||||
// Should generate 2 updates: 1 to add face1 to /a and
|
||||
// 1 to add face1 to /a/b
|
||||
insertFaceEntry("/a", 2, 0, 10, 0);
|
||||
|
||||
Rib::FibUpdateList updates = getSortedFibUpdates();
|
||||
BOOST_REQUIRE_EQUAL(updates.size(), 2);
|
||||
|
||||
Rib::FibUpdateList::const_iterator update = updates.begin();
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
|
||||
++update;
|
||||
BOOST_CHECK_EQUAL((*update)->name, "/a/b");
|
||||
BOOST_CHECK_EQUAL((*update)->faceId, 1);
|
||||
BOOST_CHECK_EQUAL((*update)->cost, 50);
|
||||
BOOST_CHECK_EQUAL((*update)->action, FibUpdate::ADD_NEXTHOP);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // UpdateFace
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // FibUpdates
|
||||
|
||||
} // namespace tests
|
||||
} // namespace rib
|
||||
} // namespace nfd
|
||||
+5
-5
@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(RibEntry)
|
||||
BOOST_CHECK_EQUAL(entry.eraseFace(face1), false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Rib_Parent)
|
||||
BOOST_AUTO_TEST_CASE(Parent)
|
||||
{
|
||||
rib::Rib rib;
|
||||
|
||||
@@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(Rib_Parent)
|
||||
BOOST_CHECK(ribEntry->getFaces().front().faceId == 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Rib_Children)
|
||||
BOOST_AUTO_TEST_CASE(Children)
|
||||
{
|
||||
rib::Rib rib;
|
||||
|
||||
@@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(Rib_Children)
|
||||
BOOST_CHECK_EQUAL((rib.find(name3)->second)->getParent()->getName(), name4);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Rib_EraseFace)
|
||||
BOOST_AUTO_TEST_CASE(EraseFace)
|
||||
{
|
||||
rib::Rib rib;
|
||||
|
||||
@@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(Rib_EraseFace)
|
||||
rib.erase(name4, entry4);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Rib_EraseRibEntry)
|
||||
BOOST_AUTO_TEST_CASE(EraseRibEntry)
|
||||
{
|
||||
rib::Rib rib;
|
||||
|
||||
@@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE(Rib_EraseRibEntry)
|
||||
BOOST_CHECK(ribEntry3->getParent() == ribEntry1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Rib_EraseByFaceId)
|
||||
BOOST_AUTO_TEST_CASE(EraseByFaceId)
|
||||
{
|
||||
rib::Rib rib;
|
||||
|
||||
|
||||
Reference in new issue
Block a user