route: Fix FIB next hop removal bug
refs: #2018
Change-Id: Id107c04d4cdce9cc756acad5d262e5c1e0cc29a8
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index b8b5b72..8f2965b 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -289,12 +289,12 @@
}
void
- setMaxFacesPerPrefix(int32_t mfpp)
+ setMaxFacesPerPrefix(uint32_t mfpp)
{
m_maxFacesPerPrefix = mfpp;
}
- int32_t
+ uint32_t
getMaxFacesPerPrefix() const
{
return m_maxFacesPerPrefix;
@@ -353,7 +353,7 @@
double m_corR;
double m_corTheta;
- int32_t m_maxFacesPerPrefix;
+ uint32_t m_maxFacesPerPrefix;
std::string m_logDir;
std::string m_seqFileDir;
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 240fffb..00b7877 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -79,7 +79,7 @@
, m_isRouteCalculationScheduled(false)
, m_isRoutingTableCalculating(false)
, m_routingTable(scheduler)
- , m_fib(*this, m_nlsrFace, scheduler)
+ , m_fib(m_nlsrFace, scheduler, m_adjacencyList, m_confParam)
, m_namePrefixTable(*this)
, m_syncLogicHandler(m_nlsrFace, m_nlsrLsdb, m_confParam)
, m_helloProtocol(*this, scheduler)
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 2010858..1815b27 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -24,14 +24,13 @@
#include <cmath>
#include <ndn-cxx/common.hpp>
-#include "nlsr.hpp"
+#include "adjacency-list.hpp"
+#include "conf-parameter.hpp"
#include "nexthop-list.hpp"
#include "face-map.hpp"
#include "fib.hpp"
#include "logger.hpp"
-
-
namespace nlsr {
INIT_LOGGER("Fib");
@@ -44,7 +43,7 @@
static bool
fibEntryNameCompare(const FibEntry& fibEntry, const ndn::Name& name)
{
- return fibEntry.getName() == name ;
+ return fibEntry.getName() == name;
}
void
@@ -93,84 +92,102 @@
}
void
-Fib::addNextHopsToFibEntryAndNfd(FibEntry& entry, NexthopList& nextHopList)
+Fib::addNextHopsToFibEntryAndNfd(FibEntry& entry, NexthopList& hopsToAdd)
{
const ndn::Name& name = entry.getName();
- nextHopList.sort();
-
- int numFaces = 0;
- int maxFaces = getNumberOfFacesForName(nextHopList,
- m_nlsr.getConfParameter().getMaxFacesPerPrefix());
-
- for (NexthopList::iterator hopIt = nextHopList.begin();
- hopIt != nextHopList.end() && numFaces < maxFaces; ++hopIt, ++numFaces)
+ for (NexthopList::iterator it = hopsToAdd.begin(); it != hopsToAdd.end(); ++it)
{
// Add nexthop to FIB entry
- entry.getNexthopList().addNextHop(*hopIt);
+ entry.getNexthopList().addNextHop(*it);
if (isPrefixUpdatable(name)) {
// Add nexthop to NDN-FIB
- registerPrefix(name, hopIt->getConnectingFaceUri(),
- hopIt->getRouteCostAsAdjustedInteger(),
+ registerPrefix(name, it->getConnectingFaceUri(),
+ it->getRouteCostAsAdjustedInteger(),
ndn::time::seconds(m_refreshTime + GRACE_PERIOD),
ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
}
}
+
+ entry.getNexthopList().sort();
+}
+
+void
+Fib::removeOldNextHopsFromFibEntryAndNfd(FibEntry& entry, const NexthopList& installedHops)
+{
+ _LOG_DEBUG("Fib::removeOldNextHopsFromFibEntryAndNfd Called");
+
+ const ndn::Name& name = entry.getName();
+ NexthopList& entryHopList = entry.getNexthopList();
+
+ for (NexthopList::iterator it = entryHopList.begin(); it != entryHopList.end();) {
+
+ const std::string& faceUri = it->getConnectingFaceUri();
+
+ // See if the nexthop is installed in NFD's FIB
+ NexthopList::const_iterator foundIt = std::find_if(installedHops.cbegin(),
+ installedHops.cend(),
+ bind(&compareFaceUri, _1, faceUri));
+
+ // The next hop is not installed
+ if (foundIt == installedHops.cend()) {
+
+ if (isPrefixUpdatable(name)) {
+ // Remove the nexthop from NDN's FIB
+ unregisterPrefix(name, it->getConnectingFaceUri());
+ }
+
+ // Remove the next hop from the FIB entry
+ _LOG_DEBUG("Removing " << it->getConnectingFaceUri() << " from " << name);
+ // Since the iterator will be invalidated on removal, dereference the original
+ // and increment the copy
+ entryHopList.removeNextHop(*(it++));
+ }
+ else {
+ ++it;
+ }
+ }
}
void
-Fib::removeOldNextHopsFromFibEntryAndNfd(FibEntry& entry, NexthopList& newHopList)
+Fib::update(const ndn::Name& name, NexthopList& allHops)
{
- _LOG_DEBUG("Fib::removeOldNextHopsFromFibEntryAndNfd Called");
- const ndn::Name& name = entry.getName();
- NexthopList& entryHopList = entry.getNexthopList();
- NexthopList itHopList = entryHopList;
+ _LOG_DEBUG("Fib::update called");
- for (NexthopList::iterator it = itHopList.begin(); it != itHopList.end(); ++it) {
+ // Sort all of the next hops so lower cost hops are prioritized
+ allHops.sort();
- // See if the nexthop is in the new nexthop list
- const std::string& faceUri = it->getConnectingFaceUri();
- NexthopList::iterator foundIt = std::find_if(newHopList.begin(),
- newHopList.end(),
- bind(&compareFaceUri, _1, faceUri));
+ // Get the max possible faces which is the minumum of the configuration setting and
+ // the length of the list of all next hops.
+ unsigned int maxFaces = getNumberOfFacesForName(allHops);
- // The next hop is not in the new nexthop list
- if (foundIt == newHopList.end()) {
- // Remove the next hop from the FIB entry
- _LOG_DEBUG("Removing " << it->getConnectingFaceUri() << " from " << name);
- entryHopList.removeNextHop(*it);
+ NexthopList hopsToAdd;
+ unsigned int nFaces = 0;
- if (isPrefixUpdatable(name)) {
- // Remove the nexthop from NDN-FIB
- unregisterPrefix(name, it->getConnectingFaceUri());
- }
- }
- }
-}
-
-void
-Fib::update(const ndn::Name& name, NexthopList& nextHopList)
-{
- _LOG_DEBUG("Fib::updateFib Called");
+ // Create a list of next hops to be installed with length == maxFaces
+ for (NexthopList::iterator it = allHops.begin(); it != allHops.end() && nFaces < maxFaces;
+ ++it, ++nFaces)
+ {
+ hopsToAdd.addNextHop(*it);
+ }
std::list<FibEntry>::iterator entryIt = std::find_if(m_table.begin(),
m_table.end(),
bind(&fibEntryNameCompare, _1, name));
+
// New FIB entry
if (entryIt == m_table.end()) {
_LOG_DEBUG("New FIB Entry");
// Don't create an entry for a name with no nexthops
- if (nextHopList.getSize() == 0) {
+ if (hopsToAdd.getSize() == 0) {
return;
}
FibEntry entry(name);
- addNextHopsToFibEntryAndNfd(entry, nextHopList);
-
- entry.getNexthopList().sort();
+ addNextHopsToFibEntryAndNfd(entry, hopsToAdd);
// Set entry's expiration time point and sequence number
entry.setExpirationTimePoint(ndn::time::system_clock::now() +
@@ -189,15 +206,14 @@
FibEntry& entry = *entryIt;
// Remove empty FIB entry
- if (nextHopList.getSize() == 0) {
+ if (hopsToAdd.getSize() == 0) {
remove(name);
return;
}
- addNextHopsToFibEntryAndNfd(entry, nextHopList);
- removeOldNextHopsFromFibEntryAndNfd(entry, nextHopList);
+ addNextHopsToFibEntryAndNfd(entry, hopsToAdd);
- entry.getNexthopList().sort();
+ removeOldNextHopsFromFibEntryAndNfd(entry, hopsToAdd);
// Set entry's expiration time point
entry.setExpirationTimePoint(ndn::time::system_clock::now() +
@@ -205,7 +221,7 @@
// Increment sequence number
entry.setSeqNo(entry.getSeqNo() + 1);
- // Cancel previosuly scheduled event
+ // Cancel previously scheduled event
m_scheduler.cancelEvent(entry.getExpiringEventId());
// Schedule entry to be refreshed
@@ -234,23 +250,24 @@
}
}
-int
-Fib::getNumberOfFacesForName(NexthopList& nextHopList,
- uint32_t maxFacesPerPrefix)
+unsigned int
+Fib::getNumberOfFacesForName(NexthopList& nextHopList)
{
- int endFace = 0;
- if ((maxFacesPerPrefix == 0) || (nextHopList.getSize() <= maxFacesPerPrefix)) {
- return nextHopList.getSize();
+ uint32_t nNextHops = static_cast<uint32_t>(nextHopList.getNextHops().size());
+ uint32_t nMaxFaces = m_confParameter.getMaxFacesPerPrefix();
+
+ // Allow all faces
+ if (nMaxFaces == 0) {
+ return nNextHops;
}
else {
- return maxFacesPerPrefix;
+ return std::min(nNextHops, nMaxFaces);
}
- return endFace;
}
bool
Fib::isPrefixUpdatable(const ndn::Name& name) {
- if (!m_nlsr.getAdjacencyList().isNeighbor(name)) {
+ if (!m_adjacencyList.isNeighbor(name)) {
return true;
}
@@ -313,7 +330,7 @@
uint64_t faceCost, const ndn::time::milliseconds& timeout,
uint64_t flags, uint8_t times)
{
- uint64_t faceId = m_nlsr.getAdjacencyList().getFaceId(faceUri);
+ uint64_t faceId = m_adjacencyList.getFaceId(faceUri);
if (faceId != 0) {
ndn::nfd::ControlParameters faceParameters;
faceParameters
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 9893ff2..e49727b 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -30,27 +30,30 @@
#include <ndn-cxx/util/time.hpp>
#include "face-map.hpp"
#include "fib-entry.hpp"
+#include "test-access-control.hpp"
namespace nlsr {
typedef ndn::function<void(const ndn::nfd::ControlParameters&)> CommandSucceedCallback;
typedef ndn::function<void(uint32_t/*code*/,const std::string&/*reason*/)> CommandFailCallback;
-class Nlsr;
-
+class AdjacencyList;
+class ConfParameter;
class Fib
{
public:
- Fib(Nlsr& nlsr, ndn::Face& face, ndn::Scheduler& scheduler)
- : m_nlsr(nlsr)
- , m_scheduler(scheduler)
+ Fib(ndn::Face& face, ndn::Scheduler& scheduler, AdjacencyList& adjacencyList, ConfParameter& conf)
+ : m_scheduler(scheduler)
, m_table()
, m_refreshTime(0)
, m_controller(face)
, m_faceMap()
+ , m_adjacencyList(adjacencyList)
+ , m_confParameter(conf)
{
}
+
~Fib()
{
}
@@ -59,7 +62,7 @@
remove(const ndn::Name& name);
void
- update(const ndn::Name& name, NexthopList& nextHopList);
+ update(const ndn::Name& name, NexthopList& allHops);
void
clean();
@@ -75,17 +78,17 @@
isPrefixUpdatable(const ndn::Name& name);
void
- addNextHopsToFibEntryAndNfd(FibEntry& entry, NexthopList& nextHopList);
+ addNextHopsToFibEntryAndNfd(FibEntry& entry, NexthopList& hopsToAdd);
void
- removeOldNextHopsFromFibEntryAndNfd(FibEntry& entry, NexthopList& newHopList);
+ removeOldNextHopsFromFibEntryAndNfd(FibEntry& entry, const NexthopList& installedHops);
void
removeHop(NexthopList& nl, const std::string& doNotRemoveHopFaceUri,
const ndn::Name& name);
- int
- getNumberOfFacesForName(NexthopList& nextHopList, uint32_t maxFacesPerPrefix);
+ unsigned int
+ getNumberOfFacesForName(NexthopList& nextHopList);
ndn::EventId
scheduleEntryExpiration(const ndn::Name& name, int32_t feSeqNum,
@@ -178,14 +181,19 @@
const std::string& message);
private:
- Nlsr& m_nlsr;
ndn::Scheduler& m_scheduler;
std::list<FibEntry> m_table;
int32_t m_refreshTime;
ndn::nfd::Controller m_controller;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
FaceMap m_faceMap;
+private:
+ AdjacencyList& m_adjacencyList;
+ ConfParameter& m_confParameter;
+
static const uint64_t GRACE_PERIOD;
};
diff --git a/src/route/nexthop-list.hpp b/src/route/nexthop-list.hpp
index 7c2011e..faf13f0 100644
--- a/src/route/nexthop-list.hpp
+++ b/src/route/nexthop-list.hpp
@@ -73,6 +73,7 @@
}
typedef std::list<NextHop>::iterator iterator;
+ typedef std::list<NextHop>::const_iterator const_iterator;
iterator
begin()
@@ -86,6 +87,18 @@
return m_nexthopList.end();
}
+ const_iterator
+ cbegin() const
+ {
+ return m_nexthopList.begin();
+ }
+
+ const_iterator
+ cend() const
+ {
+ return m_nexthopList.end();
+ }
+
void
writeLog();
diff --git a/src/test-access-control.hpp b/src/test-access-control.hpp
new file mode 100644
index 0000000..f1667e3
--- /dev/null
+++ b/src/test-access-control.hpp
@@ -0,0 +1,39 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014 University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR 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.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>
+ *
+ **/
+
+#ifndef NLSR_TEST_ACCESS_CONTROL_HPP
+#define NLSR_TEST_ACCESS_CONTROL_HPP
+
+#include "config.hpp"
+
+#ifdef WITH_TESTS
+#define VIRTUAL_WITH_TESTS virtual
+#define PUBLIC_WITH_TESTS_ELSE_PROTECTED public
+#define PUBLIC_WITH_TESTS_ELSE_PRIVATE public
+#define PROTECTED_WITH_TESTS_ELSE_PRIVATE protected
+#else
+#define VIRTUAL_WITH_TESTS
+#define PUBLIC_WITH_TESTS_ELSE_PROTECTED protected
+#define PUBLIC_WITH_TESTS_ELSE_PRIVATE private
+#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
+#endif
+
+#endif //NLSR_TEST_ACCESS_CONTROL_HPP