rib: Generate FIB updates using route flags

refs: #1325

Change-Id: I5c567da1c06819caeba5cc5b024914666ba70ab6
This commit is contained in:
Vince Lehman authored and Alex Afanasyev committed 2014-06-29 17:41:49 -07:00
1 parent dc26b2796a
commit 4387e78005
15 files changed
+2496 -46

No files matched your search

+4
View File
@@ -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
+57
View File
@@ -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
+90
View File
@@ -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
View File
@@ -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&
+72
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+112
View File
@@ -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
+396
View File
@@ -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
+272
View File
@@ -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
+202
View File
@@ -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
+266
View File
@@ -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
View File
@@ -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;