route: communicate routing changes using signals
The RoutingTable now has a signal that it emits upon finishing
calculation, which other modules can subscribe to. The NamePrefixTable
now references this emitted container to update its local copies of
routing information.
Change-Id: Id601776258ad0367cc47461ea8f86a710eada132
refs: #4249
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 32bda23..02915e4 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -53,7 +53,7 @@
, m_isRoutingTableCalculating(false)
, m_routingTable(scheduler)
, m_fib(m_nlsrFace, scheduler, m_adjacencyList, m_confParam, m_keyChain)
- , m_namePrefixTable(*this)
+ , m_namePrefixTable(*this, m_routingTable.afterRoutingChange)
, m_localhostDispatcher(m_nlsrFace, m_keyChain)
, m_routerNameDispatcher(m_nlsrFace, m_keyChain)
, m_lsdbDatasetHandler(m_nlsrLsdb,
diff --git a/src/route/name-prefix-table.cpp b/src/route/name-prefix-table.cpp
index 3b67bcb..bd7269a 100644
--- a/src/route/name-prefix-table.cpp
+++ b/src/route/name-prefix-table.cpp
@@ -33,6 +33,20 @@
INIT_LOGGER("NamePrefixTable");
+NamePrefixTable::NamePrefixTable(Nlsr& nlsr, std::shared_ptr<AfterRoutingChange>& afterRoutingChangeSignal)
+ : m_nlsr(nlsr)
+{
+ m_afterRoutingChangeConnection = afterRoutingChangeSignal->connect(
+ [this] (const std::list<RoutingTableEntry>& entries) {
+ updateWithNewRoute(entries);
+ });
+}
+
+NamePrefixTable::~NamePrefixTable()
+{
+ m_afterRoutingChangeConnection.disconnect();
+}
+
bool
npteCompare(std::shared_ptr<NamePrefixTableEntry>& npte, const ndn::Name& name)
{
@@ -196,17 +210,20 @@
}
void
-NamePrefixTable::updateWithNewRoute()
+NamePrefixTable::updateWithNewRoute(const std::list<RoutingTableEntry>& entries)
{
_LOG_DEBUG("Updating table with newly calculated routes");
// Iterate over each pool entry we have
for (auto&& poolEntryPair : m_rtpool) {
auto&& poolEntry = poolEntryPair.second;
- RoutingTableEntry* sourceEntry =
- m_nlsr.getRoutingTable().findRoutingTableEntry(poolEntry->getDestination());
+ auto sourceEntry = std::find_if(entries.begin(), entries.end(),
+ [&poolEntry] (const RoutingTableEntry& entry) {
+ return poolEntry->getDestination() == entry.getDestination();
+ });
// If this pool entry has a corresponding entry in the routing table now
- if (sourceEntry != nullptr && poolEntry->getNexthopList() != sourceEntry->getNexthopList()) {
+ if (sourceEntry != entries.end()
+ && poolEntry->getNexthopList() != sourceEntry->getNexthopList()) {
_LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " has changed next-hops.");
poolEntry->setNexthopList(sourceEntry->getNexthopList());
for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
@@ -214,14 +231,13 @@
addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
}
}
- else if (sourceEntry == nullptr) {
+ else if (sourceEntry == entries.end()) {
_LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " now has no next-hops.");
poolEntry->getNexthopList().reset();
for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
auto nameEntryFullPtr = nameEntry.second.lock();
addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
}
-
}
else {
_LOG_TRACE("No change in routing entry:" << poolEntry->getDestination()
diff --git a/src/route/name-prefix-table.hpp b/src/route/name-prefix-table.hpp
index a4dabc4..f4901ba 100644
--- a/src/route/name-prefix-table.hpp
+++ b/src/route/name-prefix-table.hpp
@@ -24,7 +24,7 @@
#include "name-prefix-table-entry.hpp"
#include "routing-table-pool-entry.hpp"
-
+#include "signals.hpp"
#include "test-access-control.hpp"
#include <list>
@@ -41,10 +41,9 @@
using NptEntryList = std::list<std::shared_ptr<NamePrefixTableEntry>>;
using const_iterator = NptEntryList::const_iterator;
- NamePrefixTable(Nlsr& nlsr)
- : m_nlsr(nlsr)
- {
- }
+ NamePrefixTable(Nlsr& nlsr, std::shared_ptr<AfterRoutingChange>& afterRoutingChangeSignal);
+
+ ~NamePrefixTable();
/*! \brief Adds a destination to the specified name prefix.
\param name The name prefix
@@ -78,14 +77,14 @@
/*! \brief Updates all routing information in the NPT.
- Naively iterates over all the NPT entries, then over each of their
- RoutingTablePoolEntries, passing the name/destination pair back to
- addEntry after updating the pool entry with new information. This
- ensures that the FIB is appropriately apprised of any changes to a
- prefix's preferred next hops.
+ Takes in a list of entries that are assumed to be exhaustive, and
+ updates each pool entry with the next hop information contained in
+ the corresponding entry in entries. If no entry is found, it is
+ assumed that the destination for that pool entry is inaccessible,
+ and its next hop information is deleted.
*/
void
- updateWithNewRoute();
+ updateWithNewRoute(const std::list<RoutingTableEntry>& entries);
/*! \brief Adds a pool entry to the pool.
\param rtpe The entry.
@@ -126,7 +125,7 @@
private:
Nlsr& m_nlsr;
-
+ ndn::util::signal::Connection m_afterRoutingChangeConnection;
};
inline NamePrefixTable::const_iterator
diff --git a/src/route/routing-table.cpp b/src/route/routing-table.cpp
index 238852a..547e943 100644
--- a/src/route/routing-table.cpp
+++ b/src/route/routing-table.cpp
@@ -34,6 +34,14 @@
INIT_LOGGER("RoutingTable");
+RoutingTable::RoutingTable(ndn::Scheduler& scheduler)
+ : afterRoutingChange{std::make_shared<AfterRoutingChange>()}
+ , m_scheduler(scheduler)
+ , m_NO_NEXT_HOP{-12345}
+ , m_routingCalcInterval{static_cast<uint32_t>(ROUTING_CALC_INTERVAL_DEFAULT)}
+{
+}
+
void
RoutingTable::calculate(Nlsr& pnlsr)
{
@@ -81,7 +89,7 @@
}
// Inform the NPT that updates have been made
_LOG_DEBUG("Calling Update NPT With new Route");
- pnlsr.getNamePrefixTable().updateWithNewRoute();
+ (*afterRoutingChange)(m_rTable);
writeLog(pnlsr.getConfParameter().getHyperbolicState());
pnlsr.getNamePrefixTable().writeLog();
pnlsr.getFib().writeLog();
@@ -98,7 +106,7 @@
clearDryRoutingTable(); // for dry run options
// need to update NPT here
_LOG_DEBUG("Calling Update NPT With new Route");
- pnlsr.getNamePrefixTable().updateWithNewRoute();
+ (*afterRoutingChange)(m_rTable);
writeLog(pnlsr.getConfParameter().getHyperbolicState());
pnlsr.getNamePrefixTable().writeLog();
pnlsr.getFib().writeLog();
diff --git a/src/route/routing-table.hpp b/src/route/routing-table.hpp
index b138c9d..274853e 100644
--- a/src/route/routing-table.hpp
+++ b/src/route/routing-table.hpp
@@ -17,14 +17,14 @@
* 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/>.
*
- * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
- *
**/
+
#ifndef NLSR_ROUTING_TABLE_HPP
#define NLSR_ROUTING_TABLE_HPP
#include "conf-parameter.hpp"
#include "routing-table-entry.hpp"
+#include "signals.hpp"
#include <iostream>
#include <utility>
@@ -40,12 +40,7 @@
class RoutingTable
{
public:
- RoutingTable(ndn::Scheduler& scheduler)
- : m_scheduler(scheduler)
- , m_NO_NEXT_HOP(-12345)
- , m_routingCalcInterval(static_cast<uint32_t>(ROUTING_CALC_INTERVAL_DEFAULT))
- {
- }
+ RoutingTable(ndn::Scheduler& scheduler);
/*! \brief Calculates a list of next hops for each router in the network.
* \param pnlsr The NLSR object that contains the LSAs needed for adj. info.
@@ -119,12 +114,17 @@
void
writeLog(int hyperbolicState);
+public:
+ std::shared_ptr<AfterRoutingChange> afterRoutingChange;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ std::list<RoutingTableEntry> m_rTable;
+
private:
ndn::Scheduler& m_scheduler;
const int m_NO_NEXT_HOP;
- std::list<RoutingTableEntry> m_rTable;
std::list<RoutingTableEntry> m_dryTable;
ndn::time::seconds m_routingCalcInterval;
diff --git a/src/signals.hpp b/src/signals.hpp
new file mode 100644
index 0000000..b8518b0
--- /dev/null
+++ b/src/signals.hpp
@@ -0,0 +1,36 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The 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_SIGNALS_HPP
+#define NLSR_SIGNALS_HPP
+
+#include <ndn-cxx/util/signal.hpp>
+
+namespace nlsr {
+
+class RoutingTable;
+class RoutingTableEntry;
+
+using AfterRoutingChange = ndn::util::Signal<RoutingTable, const std::list<RoutingTableEntry>&>;
+
+} // namespace nlsr
+
+#endif // NLSR_SIGNALS_HPP