route: updates to name prefixes are more efficent.
With this change, only entries that have changed next-hops will
cause any change in the name prefix table. Consequently, routing
table calculations no longer cause RIB registrations for unchanged
prefixes. However, this is not a problem because FIB entries
refresh themselves. This resulted in the removal of a test from the
TestNlsr suite.
refs: #2864
Change-Id: If28a04cb7bb47a3a6c32cd24578c68885d08d6b3
diff --git a/tests/test-name-prefix-table.cpp b/tests/test-name-prefix-table.cpp
index eca19f6..79cd651 100644
--- a/tests/test-name-prefix-table.cpp
+++ b/tests/test-name-prefix-table.cpp
@@ -19,9 +19,9 @@
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
**/
+#include "route/name-prefix-table.hpp"
#include "nlsr.hpp"
#include "test-common.hpp"
-#include "route/name-prefix-table.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
@@ -123,14 +123,14 @@
// Each NPT entry should have a destination router
it = npt.begin();
- BOOST_REQUIRE_EQUAL(it->getNamePrefix(), buptRouterName);
- BOOST_REQUIRE_EQUAL(it->getRteList().size(), 1);
- BOOST_CHECK_EQUAL((*it->getRteList().begin())->getDestination(), buptRouterName);
+ BOOST_REQUIRE_EQUAL((*it)->getNamePrefix(), buptRouterName);
+ BOOST_REQUIRE_EQUAL((*it)->getRteList().size(), 1);
+ BOOST_CHECK_EQUAL((*(*it)->getRteList().begin())->getDestination(), buptRouterName);
++it;
- BOOST_REQUIRE_EQUAL(it->getNamePrefix(), buptAdvertisedName);
- BOOST_REQUIRE_EQUAL(it->getRteList().size(), 1);
- BOOST_CHECK_EQUAL((*it->getRteList().begin())->getDestination(), buptRouterName);
+ BOOST_REQUIRE_EQUAL((*it)->getNamePrefix(), buptAdvertisedName);
+ BOOST_REQUIRE_EQUAL((*it)->getRteList().size(), 1);
+ BOOST_CHECK_EQUAL((*(*it)->getRteList().begin())->getDestination(), buptRouterName);
}
BOOST_FIXTURE_TEST_CASE(AddEntryToPool, NamePrefixTableFixture)
@@ -168,11 +168,13 @@
npt.addEntry("/ndn/memphis/rtr2", "/ndn/memphis/rtr1");
NamePrefixTable::NptEntryList::iterator nItr =
- std::find(npt.m_table.begin(),
- npt.m_table.end(),
- npte1);
+ std::find_if(npt.m_table.begin(),
+ npt.m_table.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry->getNamePrefix() == npte1.getNamePrefix();
+ });
- std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = nItr->getRteList();
+ std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = (*nItr)->getRteList();
std::list<std::shared_ptr<RoutingTablePoolEntry>>::iterator rItr =
std::find(rtpeList.begin(),
rtpeList.end(),
@@ -186,7 +188,7 @@
RoutingTablePoolEntry rtpe1("/ndn/memphis/rtr1", 0);
NamePrefixTableEntry npte1("/ndn/memphis/rtr2");
- npt.m_table.push_back(npte1);
+ npt.m_table.push_back(make_shared<NamePrefixTableEntry>(npte1));
npt.addEntry("/ndn/memphis/rtr2", "/ndn/memphis/rtr1");
npt.addEntry("/ndn/memphis/rtr2", "/ndn/memphis/altrtr");
@@ -194,16 +196,126 @@
npt.removeEntry("/ndn/memphis/rtr2", "/ndn/memphis/rtr1");
NamePrefixTable::NptEntryList::iterator nItr =
- std::find(npt.m_table.begin(),
- npt.m_table.end(),
- npte1);
+ std::find_if(npt.m_table.begin(),
+ npt.m_table.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry->getNamePrefix() == npte1.getNamePrefix();
+ });
- std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = nItr->getRteList();
+ std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = (*nItr)->getRteList();
BOOST_CHECK_EQUAL(rtpeList.size(), 1);
BOOST_CHECK_EQUAL(npt.m_rtpool.size(), 1);
}
+BOOST_FIXTURE_TEST_CASE(AddNptEntryPtrToRoutingEntry, NamePrefixTableFixture)
+{
+ NamePrefixTable& npt = nlsr.getNamePrefixTable();
+ NamePrefixTableEntry npte1("/ndn/memphis/rtr2");
+ npt.m_table.push_back(make_shared<NamePrefixTableEntry>(npte1));
+
+ npt.addEntry("/ndn/memphis/rtr2", "/ndn/memphis/rtr1");
+
+ NamePrefixTable::NptEntryList::iterator nItr =
+ std::find_if(npt.m_table.begin(),
+ npt.m_table.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry->getNamePrefix() == npte1.getNamePrefix();
+ });
+
+ std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = (*nItr)->getRteList();
+
+ BOOST_CHECK_EQUAL(rtpeList.size(), 1);
+
+ auto& namePrefixPtrs = rtpeList.front()->namePrefixTableEntries;
+
+ auto nptIterator = namePrefixPtrs.find(npte1.getNamePrefix());
+ BOOST_REQUIRE(nptIterator != namePrefixPtrs.end());
+ auto nptSharedPtr = nptIterator->second.lock();
+ BOOST_CHECK_EQUAL(*nptSharedPtr, npte1);
+}
+
+BOOST_FIXTURE_TEST_CASE(RemoveNptEntryPtrFromRoutingEntry, NamePrefixTableFixture)
+{
+ NamePrefixTable& npt = nlsr.getNamePrefixTable();
+ NamePrefixTableEntry npte1("/ndn/memphis/rtr1");
+ NamePrefixTableEntry npte2("/ndn/memphis/rtr2");
+ RoutingTableEntry rte1("/ndn/memphis/destination1");
+ npt.m_table.push_back(make_shared<NamePrefixTableEntry>(npte1));
+ npt.m_table.push_back(make_shared<NamePrefixTableEntry>(npte2));
+
+ npt.addEntry(npte1.getNamePrefix(), rte1.getDestination());
+ // We have to add two entries, otherwise the routing pool entry will be deleted.
+ npt.addEntry(npte2.getNamePrefix(), rte1.getDestination());
+ npt.removeEntry(npte2.getNamePrefix(), rte1.getDestination());
+
+ NamePrefixTable::NptEntryList::iterator nItr =
+ std::find_if(npt.m_table.begin(),
+ npt.m_table.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry->getNamePrefix() == npte1.getNamePrefix();
+ });
+
+ std::list<std::shared_ptr<RoutingTablePoolEntry>> rtpeList = (*nItr)->getRteList();
+
+ BOOST_CHECK_EQUAL(rtpeList.size(), 1);
+
+ auto& namePrefixPtrs = rtpeList.front()->namePrefixTableEntries;
+
+ // We should have removed the second one
+ BOOST_CHECK_EQUAL(namePrefixPtrs.size(), 1);
+
+ auto nptIterator = namePrefixPtrs.find(npte1.getNamePrefix());
+
+ BOOST_REQUIRE(nptIterator != namePrefixPtrs.end());
+ auto nptSharedPtr = nptIterator->second.lock();
+ BOOST_CHECK_EQUAL(*nptSharedPtr, npte1);
+}
+
+BOOST_FIXTURE_TEST_CASE(RoutingTableUpdate, NamePrefixTableFixture)
+{
+ NamePrefixTable& namePrefixTable = nlsr.getNamePrefixTable();
+ RoutingTable& routingTable = nlsr.getRoutingTable();
+ const ndn::Name destination = ndn::Name{"/ndn/destination1"};
+ NextHop hop1{"upd4://10.0.0.1", 0};
+ NextHop hop2{"udp4://10.0.0.2", 1};
+ NextHop hop3{"udp4://10.0.0.3", 2};
+ const NamePrefixTableEntry entry1{"/ndn/router1"};
+ namePrefixTable.addEntry(entry1.getNamePrefix(), destination);
+
+ routingTable.addNextHop(destination, hop1);
+ routingTable.addNextHop(destination, hop2);
+
+ namePrefixTable.updateWithNewRoute();
+
+ // At this point the NamePrefixTableEntry should have two NextHops.
+ auto nameIterator = std::find_if(namePrefixTable.begin(), namePrefixTable.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry1.getNamePrefix() == entry->getNamePrefix();
+ });
+ BOOST_REQUIRE(nameIterator != namePrefixTable.end());
+
+ auto iterator = namePrefixTable.m_rtpool.find(destination);
+ BOOST_REQUIRE(iterator != namePrefixTable.m_rtpool.end());
+ auto nextHops = (iterator->second)->getNexthopList();
+ BOOST_CHECK_EQUAL(nextHops.getSize(), 2);
+
+ // Add the other NextHop
+ routingTable.addNextHop(destination, hop3);
+ namePrefixTable.updateWithNewRoute();
+
+ // At this point the NamePrefixTableEntry should have three NextHops.
+ nameIterator = std::find_if(namePrefixTable.begin(), namePrefixTable.end(),
+ [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
+ return entry1.getNamePrefix() == entry->getNamePrefix();
+ });
+ BOOST_REQUIRE(nameIterator != namePrefixTable.end());
+ iterator = namePrefixTable.m_rtpool.find(destination);
+ BOOST_REQUIRE(iterator != namePrefixTable.m_rtpool.end());
+ nextHops = (iterator->second)->getNexthopList();
+ BOOST_CHECK_EQUAL(nextHops.getSize(), 3);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace test
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index cba776b..502d5f6 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -22,6 +22,7 @@
#include "nlsr.hpp"
#include "test-common.hpp"
#include "control-commands.hpp"
+#include "logger.hpp"
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
@@ -315,118 +316,6 @@
BOOST_CHECK(rtEntry == nullptr);
}
-// Bug #2733
-// This test checks that when a face for an inactive node is destroyed, an
-// Adjacency LSA build does not postpone the LSA refresh and cause RIB
-// entries for other nodes' name prefixes to not be refreshed.
-//
-// This test is invalid when Issue #2732 is implemented since an Adjacency LSA
-// refresh will not cause RIB entries for other nodes' name prefixes to be refreshed.
-BOOST_FIXTURE_TEST_CASE(FaceDestroyEventInactive, UnitTestTimeFixture)
-{
- std::shared_ptr<ndn::util::DummyClientFace> face = std::make_shared<ndn::util::DummyClientFace>(g_ioService);
- Nlsr nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain);
- Lsdb& lsdb = nlsr.getLsdb();
-
- // Simulate loading configuration file
- ConfParameter& conf = nlsr.getConfParameter();
- conf.setNetwork("/ndn");
- conf.setSiteName("/site");
- conf.setRouterName("/%C1.router/this-router");
- conf.setFirstHelloInterval(0);
- conf.setAdjLsaBuildInterval(0);
- conf.setRoutingCalcInterval(0);
-
- // Add neighbors
- AdjacencyList& neighbors = nlsr.getAdjacencyList();
-
- uint64_t destroyFaceId = 128;
-
- // Create an inactive neighbor whose Face will be destroyed
- Adjacent failNeighbor("/ndn/neighborA", ndn::util::FaceUri("udp4://10.0.0.1"), 10, Adjacent::STATUS_INACTIVE, 3,
- destroyFaceId);
- neighbors.insert(failNeighbor);
-
- // Create an additional active neighbor so an adjacency LSA can be built
- Adjacent otherNeighbor("/ndn/neighborB", ndn::util::FaceUri("udp4://10.0.0.2"), 25, Adjacent::STATUS_ACTIVE, 0, 256);
- neighbors.insert(otherNeighbor);
-
- // Add a name for the neighbor to advertise
- NamePrefixList nameList;
- ndn::Name nameToAdvertise("/ndn/neighborB/name");
- nameList.insert(nameToAdvertise);
-
- NameLsa nameLsa("/ndn/neighborB", 25, ndn::time::system_clock::now(), nameList);
- lsdb.installNameLsa(nameLsa);
-
- nlsr.initialize();
-
- // Simulate successful HELLO responses from neighbor B
- lsdb.scheduleAdjLsaBuild();
-
- // Set up adjacency LSAs
- // This router
- Adjacent thisRouter(conf.getRouterPrefix(), ndn::util::FaceUri("udp4://10.0.0.2"), 25, Adjacent::STATUS_ACTIVE, 0, 256);
-
- AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10, ndn::time::system_clock::now(), 1, neighbors);
- lsdb.installAdjLsa(ownAdjLsa);
-
- // Other ACTIVE router
- AdjacencyList otherAdjacencies;
- otherAdjacencies.insert(thisRouter);
-
- AdjLsa otherAdjLsa("/ndn/neighborB", 10,
- ndn::time::system_clock::now() + ndn::time::seconds(3600), 1, otherAdjacencies);
-
- lsdb.installAdjLsa(otherAdjLsa);
-
- // Run the scheduler to build an adjacency LSA
- this->advanceClocks(ndn::time::milliseconds(1));
-
- ndn::Name key = ndn::Name(nlsr.getConfParameter().getRouterPrefix()).append(AdjLsa::TYPE_STRING);
- AdjLsa* lsa = lsdb.findAdjLsa(key);
- BOOST_REQUIRE(lsa != nullptr);
-
- // Cancel previous LSA expiration event
- g_scheduler.cancelEvent(lsa->getExpiringEventId());
-
- // Set expiration time for own Adjacency LSA to earlier value for unit-test
- //
- // Expiration time is negative to offset the GRACE_PERIOD (10 seconds) automatically applied
- // to expiration times
- ndn::EventId id = lsdb.scheduleAdjLsaExpiration(key, lsa->getLsSeqNo(), -ndn::time::seconds(9));
- lsa->setExpiringEventId(id);
-
- // Generate a FaceEventDestroyed notification
- ndn::nfd::FaceEventNotification event;
- event.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
- .setFaceId(destroyFaceId);
-
- std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
- data->setContent(event.wireEncode());
- nlsr.getKeyChain().sign(*data);
-
- // Receive the FaceEventDestroyed notification
- face->receive(*data);
-
- // Run the scheduler to expire the Adjacency LSA. The expiration should refresh the RIB
- // entries associated with Neighbor B's advertised prefix.
- face->sentInterests.clear();
- this->advanceClocks(ndn::time::seconds(1));
-
- // The Face should have two sent Interests: the face event and a RIB registration
- BOOST_REQUIRE(face->sentInterests.size() > 0);
- const ndn::Interest& interest = face->sentInterests.back();
-
- ndn::nfd::ControlParameters parameters;
- ndn::Name::Component verb;
- BOOST_REQUIRE_NO_THROW(extractRibCommandParameters(interest,
- verb,
- parameters));
- BOOST_CHECK_EQUAL(verb, ndn::Name::Component("register"));
- BOOST_CHECK_EQUAL(parameters.getName(), nameToAdvertise);
-}
-
BOOST_AUTO_TEST_CASE(GetCertificate)
{
// Create certificate