lsdb: rebuild using boost::multi_index to replace 3 LSA lists
refs: #4127
Co-authored-by: Nick Gordon <nmgordon@memphis.edu>
Change-Id: Ic179f90019e472157b0d61c6db02a4afaf4843b6
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 9913751..fb4bcb7 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -25,14 +25,10 @@
#include "nlsr.hpp"
#include "utility/name-helper.hpp"
-#include <ndn-cxx/security/signing-helpers.hpp>
-
namespace nlsr {
INIT_LOGGER(Lsdb);
-const ndn::Name::Component Lsdb::NAME_COMPONENT = ndn::Name::Component("lsdb");
-const ndn::time::seconds Lsdb::GRACE_PERIOD = ndn::time::seconds(10);
const ndn::time::steady_clock::TimePoint Lsdb::DEFAULT_LSA_RETRIEVAL_DEADLINE =
ndn::time::steady_clock::TimePoint::min();
@@ -49,8 +45,8 @@
return isLsaNew(routerName, lsaType, sequenceNumber);
}, m_confParam)
, m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
- , m_thisRouterPrefix(m_confParam.getRouterPrefix().toUri())
, m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
+ , m_thisRouterPrefix(m_confParam.getRouterPrefix())
, m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
, m_onNewLsaConnection(m_sync.onNewLsa->connect(
[this] (const ndn::Name& updateName, uint64_t sequenceNumber,
@@ -65,521 +61,33 @@
{
}
-Lsdb::~Lsdb()
-{
- for (const auto& sp : m_fetchers) {
- sp->stop();
- }
-}
-
void
-Lsdb::onFetchLsaError(uint32_t errorCode,
- const std::string& msg,
- const ndn::Name& interestName,
- uint32_t retransmitNo,
- const ndn::time::steady_clock::TimePoint& deadline,
- ndn::Name lsaName,
- uint64_t seqNo)
-{
- NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
- << ", Message: " << msg);
-
- if (ndn::time::steady_clock::now() < deadline) {
- auto it = m_highestSeqNo.find(lsaName);
- if (it != m_highestSeqNo.end() && it->second == seqNo) {
- // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
- // immediately since at the least the LSA Interest lifetime has elapsed.
- // Otherwise, it is necessary to delay the Interest re-expression to prevent
- // the potential for constant Interest flooding.
- ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
-
- if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
- delay = ndn::time::seconds(0);
- }
-
- m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
- interestName, retransmitNo + 1, deadline));
- }
- }
-}
-
-void
-Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
-{
- NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
-
- ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
- uint64_t seqNo = interestName[-1].toNumber();
-
- if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
- m_highestSeqNo[lsaName] = seqNo;
- }
- else if (seqNo > m_highestSeqNo[lsaName]) {
- m_highestSeqNo[lsaName] = seqNo;
- NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
- }
- else if (seqNo < m_highestSeqNo[lsaName]) {
- return;
- }
-
- std::string chkString("LSA");
- int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
-
- if (lsaPosition >= 0) {
- // Extracts the prefix of the originating router from the data.
- ndn::Name originRouter = m_confParam.getNetwork();
- originRouter.append(interestName.getSubName(lsaPosition + 1,
- interestName.size() - lsaPosition - 3));
-
- try {
- ndn::Block block(bufferPtr);
- Lsa::Type interestedLsType;
- std::istringstream(interestName[-2].toUri()) >> interestedLsType;
-
- if (interestedLsType == Lsa::Type::NAME) {
- processContentNameLsa(originRouter.append(boost::lexical_cast<std::string>(interestedLsType)),
- seqNo,
- block);
- }
- else if (interestedLsType == Lsa::Type::ADJACENCY) {
- processContentAdjacencyLsa(originRouter.append(boost::lexical_cast<std::string>(interestedLsType)),
- seqNo,
- block);
- }
- else if (interestedLsType == Lsa::Type::COORDINATE) {
- processContentCoordinateLsa(originRouter.append(boost::lexical_cast<std::string>(interestedLsType)),
- seqNo,
- block);
- }
- else {
- NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestedLsType);
- }
- }
- catch (const std::exception& e) {
- NLSR_LOG_TRACE("LSA data decoding error :( " << e.what());
- return;
- }
-
- lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
- }
-}
-
- /*! \brief Compares if a name LSA is the same as the one specified by key
-
- \param nlsa1 A name LSA object
- \param key A key of an originating router to compare to nlsa1
- */
-static bool
-nameLsaCompareByKey(const NameLsa& nlsa1, const ndn::Name& key)
-{
- return nlsa1.getKey() == key;
-}
-
-bool
Lsdb::buildAndInstallOwnNameLsa()
{
- NameLsa nameLsa(m_confParam.getRouterPrefix(),
- m_sequencingManager.getNameLsaSeq() + 1,
- getLsaExpirationTimePoint(),
- m_confParam.getNamePrefixList());
+ NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
+ getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
m_sequencingManager.increaseNameLsaSeq();
-
m_sequencingManager.writeSeqNoToFile();
m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
- return installNameLsa(nameLsa);
-}
-
-NameLsa*
-Lsdb::findNameLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
- std::bind(nameLsaCompareByKey, _1, key));
- if (it != m_nameLsdb.end()) {
- return &*it;
- }
- return nullptr;
-}
-
-bool
-Lsdb::isNameLsaNew(const ndn::Name& key, uint64_t seqNo)
-{
- NameLsa* nameLsaCheck = findNameLsa(key);
- // Is the name in the LSDB
- if (nameLsaCheck != nullptr) {
- // And the supplied seq no is the highest so far
- if (nameLsaCheck->getSeqNo() < seqNo) {
- return true;
- }
- else {
- return false;
- }
- }
- return true;
-}
-
-ndn::scheduler::EventId
-Lsdb::scheduleNameLsaExpiration(const ndn::Name& key, int seqNo,
- const ndn::time::seconds& expTime)
-{
- return m_scheduler.schedule(expTime + GRACE_PERIOD,
- std::bind(&Lsdb::expireOrRefreshNameLsa, this, key, seqNo));
-}
-
-bool
-Lsdb::installNameLsa(NameLsa& nlsa)
-{
- NLSR_LOG_TRACE("installNameLsa");
- ndn::time::seconds timeToExpire = m_lsaRefreshTime;
- NameLsa* chkNameLsa = findNameLsa(nlsa.getKey());
- // Determines if the name LSA is new or not.
- if (chkNameLsa == nullptr) {
- addNameLsa(nlsa);
- NLSR_LOG_DEBUG("New Name LSA");
- NLSR_LOG_DEBUG("Adding Name Lsa");
- NLSR_LOG_DEBUG(nlsa);
-
- NLSR_LOG_TRACE("nlsa.getOriginRouter(): " << nlsa.getOriginRouter());
- NLSR_LOG_TRACE("m_confParam.getRouterPrefix(): " << m_confParam.getRouterPrefix());
-
- if (nlsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- // If this name LSA is from another router, add the advertised
- // prefixes to the NPT.
- m_namePrefixTable.addEntry(nlsa.getOriginRouter(), nlsa.getOriginRouter());
-
- for (const auto& name : nlsa.getNpl().getNames()) {
- if (name != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.addEntry(name, nlsa.getOriginRouter());
- }
- }
- auto duration = nlsa.getExpirationTimePoint() - ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
-
- nlsa.setExpiringEventId(scheduleNameLsaExpiration(nlsa.getKey(),
- nlsa.getSeqNo(),
- timeToExpire));
- }
- // Else this is a known name LSA, so we are updating it.
- else {
- NLSR_LOG_TRACE("Known name lsa");
- NLSR_LOG_TRACE("chkNameLsa->getSeqNo(): " << chkNameLsa->getSeqNo());
- NLSR_LOG_TRACE("nlsa.getSeqNo(): " << nlsa.getSeqNo());
- if (chkNameLsa->getSeqNo() < nlsa.getSeqNo()) {
- NLSR_LOG_DEBUG("Updated Name LSA. Updating LSDB");
- NLSR_LOG_DEBUG("Deleting Name Lsa");
- NLSR_LOG_DEBUG(chkNameLsa);
- chkNameLsa->setSeqNo(nlsa.getSeqNo());
- chkNameLsa->setExpirationTimePoint(nlsa.getExpirationTimePoint());
- chkNameLsa->getNpl().sort();
- nlsa.getNpl().sort();
- // Obtain the set difference of the current and the incoming
- // name prefix sets, and add those.
- std::list<ndn::Name> newNames = nlsa.getNpl().getNames();
- std::list<ndn::Name> oldNames = chkNameLsa->getNpl().getNames();
- std::list<ndn::Name> namesToAdd;
- std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
- std::inserter(namesToAdd, namesToAdd.begin()));
- for (const auto& name : namesToAdd) {
- chkNameLsa->addName(name);
- if (nlsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- if (name != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.addEntry(name, nlsa.getOriginRouter());
- }
- }
- }
-
- chkNameLsa->getNpl().sort();
-
- // Also remove any names that are no longer being advertised.
- std::list<ndn::Name> namesToRemove;
- std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
- std::inserter(namesToRemove, namesToRemove.begin()));
- for (const auto& name : namesToRemove) {
- NLSR_LOG_DEBUG("Removing name LSA no longer advertised: " << name);
- chkNameLsa->removeName(name);
- if (nlsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- if (name != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.removeEntry(name, nlsa.getOriginRouter());
- }
- }
- }
-
- if (nlsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- auto duration = nlsa.getExpirationTimePoint() - ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
- chkNameLsa->getExpiringEventId().cancel();
- chkNameLsa->setExpiringEventId(scheduleNameLsaExpiration(nlsa.getKey(),
- nlsa.getSeqNo(),
- timeToExpire));
- NLSR_LOG_DEBUG("Adding Name Lsa");
- NLSR_LOG_DEBUG(chkNameLsa);
- }
- }
- return true;
-}
-
-bool
-Lsdb::addNameLsa(NameLsa& nlsa)
-{
- auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
- std::bind(nameLsaCompareByKey, _1, nlsa.getKey()));
- if (it == m_nameLsdb.end()) {
- m_nameLsdb.push_back(nlsa);
- return true;
- }
- return false;
-}
-
-bool
-Lsdb::removeNameLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
- std::bind(nameLsaCompareByKey, _1, key));
- if (it != m_nameLsdb.end()) {
- NLSR_LOG_DEBUG("Deleting Name Lsa");
- NLSR_LOG_DEBUG(*it);
- // If the requested name LSA is not ours, we also need to remove
- // its entries from the NPT.
- if (it->getOriginRouter() != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.removeEntry(it->getOriginRouter(), it->getOriginRouter());
-
- for (const auto& name : it->getNpl().getNames()) {
- if (name != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.removeEntry(name, it->getOriginRouter());
- }
- }
- }
- m_nameLsdb.erase(it);
- return true;
- }
- return false;
-}
-
-bool
-Lsdb::doesNameLsaExist(const ndn::Name& key)
-{
- auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
- std::bind(nameLsaCompareByKey, _1, key));
- return it != m_nameLsdb.end();
+ installLsa(std::make_shared<NameLsa>(nameLsa));
}
void
-Lsdb::writeNameLsdbLog()
-{
- NLSR_LOG_TRACE("---------------Name LSDB-------------------");
- for (const auto& nlsa : m_nameLsdb) {
- NLSR_LOG_TRACE(nlsa);
- }
-}
-
-const std::list<NameLsa>&
-Lsdb::getNameLsdb() const
-{
- return m_nameLsdb;
-}
-
-// Cor LSA and LSDB related Functions start here
-
-/*! \brief Compares whether an LSA object is the same as a key.
- \param clsa The cor. LSA to check the identity of.
- \param key The key of the publishing router to check against.
-*/
-static bool
-corLsaCompareByKey(const CoordinateLsa& clsa, const ndn::Name& key)
-{
- return clsa.getKey() == key;
-}
-
-bool
Lsdb::buildAndInstallOwnCoordinateLsa()
{
- CoordinateLsa corLsa(m_confParam.getRouterPrefix(),
- m_sequencingManager.getCorLsaSeq() + 1,
- getLsaExpirationTimePoint(),
- m_confParam.getCorR(),
+ CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
+ getLsaExpirationTimePoint(), m_confParam.getCorR(),
m_confParam.getCorTheta());
+ m_sequencingManager.increaseCorLsaSeq();
+ m_sequencingManager.writeSeqNoToFile();
// Sync coordinate LSAs if using HR or HR dry run.
if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- m_sequencingManager.increaseCorLsaSeq();
- m_sequencingManager.writeSeqNoToFile();
m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
}
- installCoordinateLsa(corLsa);
-
- return true;
-}
-
-CoordinateLsa*
-Lsdb::findCoordinateLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
- std::bind(corLsaCompareByKey, _1, key));
- if (it != m_corLsdb.end()) {
- return &*it;
- }
- return nullptr;
-}
-
-bool
-Lsdb::isCoordinateLsaNew(const ndn::Name& key, uint64_t seqNo)
-{
- CoordinateLsa* clsa = findCoordinateLsa(key);
- // Is the coordinate LSA in the LSDB already
- if (clsa != nullptr) {
- // And the seq no is newer (higher) than the current one
- if (clsa->getSeqNo() < seqNo) {
- return true;
- }
- else {
- return false;
- }
- }
- return true;
-}
-
- // Schedules a refresh/expire event in the scheduler.
- // \param key The name of the router that published the LSA.
- // \param seqNo the seq. no. associated with the LSA to check.
- // \param expTime How long to wait before triggering the event.
-ndn::scheduler::EventId
-Lsdb::scheduleCoordinateLsaExpiration(const ndn::Name& key, int seqNo,
- const ndn::time::seconds& expTime)
-{
- return m_scheduler.schedule(expTime + GRACE_PERIOD,
- std::bind(&Lsdb::expireOrRefreshCoordinateLsa, this, key, seqNo));
-}
-
-bool
-Lsdb::installCoordinateLsa(CoordinateLsa& clsa)
-{
- ndn::time::seconds timeToExpire = m_lsaRefreshTime;
- CoordinateLsa* chkCorLsa = findCoordinateLsa(clsa.getKey());
- // Checking whether the LSA is new or not.
- if (chkCorLsa == nullptr) {
- NLSR_LOG_DEBUG("New Coordinate LSA. Adding to LSDB");
- NLSR_LOG_DEBUG("Adding Coordinate Lsa");
- NLSR_LOG_DEBUG(clsa);
- addCoordinateLsa(clsa);
-
- // Register the LSA's origin router prefix
- if (clsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.addEntry(clsa.getOriginRouter(), clsa.getOriginRouter());
- }
- if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- m_routingTable.scheduleRoutingTableCalculation();
- }
- // Set the expiration time for the new LSA.
- if (clsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- auto duration = clsa.getExpirationTimePoint() - ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
- scheduleCoordinateLsaExpiration(clsa.getKey(), clsa.getSeqNo(), timeToExpire);
- }
- // We are just updating this LSA.
- else {
- if (chkCorLsa->getSeqNo() < clsa.getSeqNo()) {
- NLSR_LOG_DEBUG("Updated Coordinate LSA. Updating LSDB");
- NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
- NLSR_LOG_DEBUG(chkCorLsa);
- chkCorLsa->setSeqNo(clsa.getSeqNo());
- chkCorLsa->setExpirationTimePoint(clsa.getExpirationTimePoint());
- // If the new LSA contains new routing information, update the LSDB with it.
- if (!chkCorLsa->isEqualContent(clsa)) {
- chkCorLsa->setCorRadius(clsa.getCorRadius());
- chkCorLsa->setCorTheta(clsa.getCorTheta());
- if (m_confParam.getHyperbolicState() >= HYPERBOLIC_STATE_ON) {
- m_routingTable.scheduleRoutingTableCalculation();
- }
- }
- // If this is an LSA from another router, refresh its expiration time.
- if (clsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- auto duration = clsa.getExpirationTimePoint() - ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
- chkCorLsa->getExpiringEventId().cancel();
- chkCorLsa->setExpiringEventId(scheduleCoordinateLsaExpiration(clsa.getKey(),
- clsa.getSeqNo(),
- timeToExpire));
- NLSR_LOG_DEBUG("Adding Coordinate Lsa");
- NLSR_LOG_DEBUG(chkCorLsa);
- }
- }
- return true;
-}
-
-bool
-Lsdb::addCoordinateLsa(CoordinateLsa& clsa)
-{
- auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
- std::bind(corLsaCompareByKey, _1, clsa.getKey()));
- if (it == m_corLsdb.end()) {
- m_corLsdb.push_back(clsa);
- return true;
- }
- return false;
-}
-
-bool
-Lsdb::removeCoordinateLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
- std::bind(corLsaCompareByKey, _1, key));
-
- if (it != m_corLsdb.end()) {
- NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
- NLSR_LOG_DEBUG(*it);
-
- if (it->getOriginRouter() != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.removeEntry(it->getOriginRouter(), it->getOriginRouter());
- }
-
- m_corLsdb.erase(it);
- return true;
- }
- return false;
-}
-
-bool
-Lsdb::doesCoordinateLsaExist(const ndn::Name& key)
-{
- auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
- std::bind(corLsaCompareByKey, _1, key));
- return it != m_corLsdb.end();
-}
-
-void
-Lsdb::writeCorLsdbLog()
-{
- if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
- return;
- }
-
- NLSR_LOG_DEBUG("---------------Cor LSDB-------------------");
- for (const auto& corLsa : m_corLsdb) {
- NLSR_LOG_DEBUG(corLsa);
- }
-}
-
-const std::list<CoordinateLsa>&
-Lsdb::getCoordinateLsdb() const
-{
- return m_corLsdb;
-}
-
-// Adj LSA and LSDB related function starts here
-
- /*! \brief Returns whether an adj. LSA object is from some router.
- \param alsa The adj. LSA object.
- \param key The router name that you want to compare the LSA with.
- */
-static bool
-adjLsaCompareByKey(AdjLsa& alsa, const ndn::Name& key)
-{
- return alsa.getKey() == key;
+ installLsa(std::make_shared<CoordinateLsa>(corLsa));
}
void
@@ -603,10 +111,258 @@
m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
}
+template<typename T>
+void
+Lsdb::writeLog() const
+{
+ if ((T::type() == Lsa::Type::COORDINATE &&
+ m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) ||
+ (T::type() == Lsa::Type::ADJACENCY &&
+ m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON)) {
+ return;
+ }
+
+ NLSR_LOG_DEBUG("---------------" << T::type() << " LSDB-------------------");
+ auto lsaRange = m_lsdb.get<byType>().equal_range(T::type());
+ for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
+ auto lsaPtr = std::static_pointer_cast<T>(*lsaIt);
+ NLSR_LOG_DEBUG(lsaPtr->toString());
+ }
+}
+
+void
+Lsdb::writeLog() const
+{
+ writeLog<CoordinateLsa>();
+ writeLog<NameLsa>();
+ writeLog<AdjLsa>();
+}
+
+void
+Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
+{
+ ndn::Name interestName(interest.getName());
+ NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
+
+ if (interestName[-2].isVersion()) {
+ // Interest for particular segment
+ if (m_segmentPublisher.replyFromStore(interestName)) {
+ NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
+ return;
+ }
+ // Remove version and segment
+ interestName = interestName.getSubName(0, interestName.size() - 2);
+ NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
+ }
+
+ // increment RCV_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
+
+ std::string chkString("LSA");
+ int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
+
+ // Forms the name of the router that the Interest packet came from.
+ ndn::Name originRouter = m_confParam.getNetwork();
+ originRouter.append(interestName.getSubName(lsaPosition + 1,
+ interestName.size() - lsaPosition - 3));
+
+ // if the interest is for this router's LSA
+ if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
+ uint64_t seqNo = interestName[-1].toNumber();
+ NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
+
+ std::string lsaType = interestName[-2].toUri();
+ Lsa::Type interestedLsType;
+ std::istringstream(lsaType) >> interestedLsType;
+ if (interestedLsType == Lsa::Type::BASE) {
+ NLSR_LOG_WARN("Received unrecognized LSA type: " << lsaType);
+ return;
+ }
+
+ incrementInterestRcvdStats(interestedLsType);
+ if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
+ lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
+ }
+ }
+ // else the interest is for other router's LSA, serve signed data from LsaSegmentStorage
+ else if (auto lsaSegment = m_lsaStorage.find(interest)) {
+ NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
+ m_face.put(*lsaSegment);
+ }
+}
+
+bool
+Lsdb::processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
+ Lsa::Type lsaType, uint64_t seqNo)
+{
+ NLSR_LOG_DEBUG(interest << " received for " << lsaType);
+ if (auto lsaPtr = findLsa(originRouter, lsaType)) {
+ NLSR_LOG_TRACE("Verifying SeqNo for " << lsaType << " is same as requested.");
+ if (lsaPtr->getSeqNo() == seqNo) {
+ m_segmentPublisher.publish(interest.getName(), interest.getName(),
+ lsaPtr->wireEncode(),
+ m_lsaRefreshTime, m_confParam.getSigningInfo());
+ incrementDataSentStats(lsaType);
+ return true;
+ }
+ }
+ else {
+ NLSR_LOG_TRACE(interest << " was not found in our LSDB");
+ }
+ return false;
+}
+
+void
+Lsdb::installLsa(shared_ptr<Lsa> lsa)
+{
+ auto timeToExpire = m_lsaRefreshTime;
+
+ auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
+ if (chkLsa == nullptr) {
+ NLSR_LOG_DEBUG("Adding " << lsa->getType() << " LSA");
+ NLSR_LOG_DEBUG(lsa->toString());
+ ndn::time::seconds timeToExpire = m_lsaRefreshTime;
+
+ m_lsdb.emplace(lsa);
+
+ // Add any new name prefixes to the NPT if from another router
+ if (lsa->getOriginRouter() != m_thisRouterPrefix) {
+ // Pass the origin router as both the name to register and where it came from.
+ m_namePrefixTable.addEntry(lsa->getOriginRouter(), lsa->getOriginRouter());
+
+ if (lsa->getType() == Lsa::Type::NAME) {
+ auto nlsa = std::static_pointer_cast<NameLsa>(lsa);
+ for (const auto& name : nlsa->getNpl().getNames()) {
+ if (name != m_thisRouterPrefix) {
+ m_namePrefixTable.addEntry(name, nlsa->getOriginRouter());
+ }
+ }
+ }
+
+ auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
+ if (duration > ndn::time::seconds(0)) {
+ timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
+ }
+ }
+
+ if ((lsa->getType() == Lsa::Type::ADJACENCY && m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON)||
+ (lsa->getType() == Lsa::Type::COORDINATE && m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF)) {
+ m_routingTable.scheduleRoutingTableCalculation();
+ }
+
+ lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
+ }
+ // Else this is a known name LSA, so we are updating it.
+ else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
+ NLSR_LOG_DEBUG("Updating " << lsa->getType() << " LSA:");
+ NLSR_LOG_DEBUG(chkLsa->toString());
+ chkLsa->setSeqNo(lsa->getSeqNo());
+ chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
+
+ if (lsa->getType() == Lsa::Type::NAME) {
+ auto chkNameLsa = std::static_pointer_cast<NameLsa>(chkLsa);
+ auto nlsa = std::static_pointer_cast<NameLsa>(lsa);
+ chkNameLsa->getNpl().sort();
+ nlsa->getNpl().sort();
+ if (!chkNameLsa->isEqualContent(*nlsa)) {
+ // Obtain the set difference of the current and the incoming
+ // name prefix sets, and add those.
+ std::list<ndn::Name> newNames = nlsa->getNpl().getNames();
+ std::list<ndn::Name> oldNames = chkNameLsa->getNpl().getNames();
+ std::list<ndn::Name> namesToAdd;
+ std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
+ std::inserter(namesToAdd, namesToAdd.begin()));
+ for (const auto& name : namesToAdd) {
+ chkNameLsa->addName(name);
+ if (nlsa->getOriginRouter() != m_thisRouterPrefix && name != m_thisRouterPrefix) {
+ m_namePrefixTable.addEntry(name, nlsa->getOriginRouter());
+ }
+ }
+
+ chkNameLsa->getNpl().sort();
+
+ // Also remove any names that are no longer being advertised.
+ std::list<ndn::Name> namesToRemove;
+ std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
+ std::inserter(namesToRemove, namesToRemove.begin()));
+ for (const auto& name : namesToRemove) {
+ NLSR_LOG_DEBUG("Removing name" << name << " from Name LSA no longer advertised.");
+ chkNameLsa->removeName(name);
+ if (nlsa->getOriginRouter() != m_thisRouterPrefix && name != m_thisRouterPrefix) {
+ m_namePrefixTable.removeEntry(name, nlsa->getOriginRouter());
+ }
+ }
+ }
+ }
+ else if (lsa->getType() == Lsa::Type::ADJACENCY) {
+ auto chkAdjLsa = std::static_pointer_cast<AdjLsa>(chkLsa);
+ auto alsa = std::static_pointer_cast<AdjLsa>(lsa);
+ if (!chkAdjLsa->isEqualContent(*alsa)) {
+ chkAdjLsa->resetAdl();
+ for (const auto& adjacent : alsa->getAdl()) {
+ chkAdjLsa->addAdjacent(adjacent);
+ }
+ m_routingTable.scheduleRoutingTableCalculation();
+ }
+ }
+ else {
+ auto chkCorLsa = std::static_pointer_cast<CoordinateLsa>(chkLsa);
+ auto clsa = std::static_pointer_cast<CoordinateLsa>(lsa);
+ if (!chkCorLsa->isEqualContent(*clsa)) {
+ chkCorLsa->setCorRadius(clsa->getCorRadius());
+ chkCorLsa->setCorTheta(clsa->getCorTheta());
+ if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
+ m_routingTable.scheduleRoutingTableCalculation();
+ }
+ }
+ }
+
+ if (chkLsa->getOriginRouter() != m_thisRouterPrefix) {
+ auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
+ if (duration > ndn::time::seconds(0)) {
+ timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
+ }
+ }
+ chkLsa->getExpiringEventId().cancel();
+ chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
+ NLSR_LOG_DEBUG("Updated " << lsa->getType() << " LSA:");
+ NLSR_LOG_DEBUG(chkLsa->toString());
+ }
+}
+
+bool
+Lsdb::removeLsa(const ndn::Name& router, Lsa::Type lsaType)
+{
+ auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
+
+ if (lsaIt != m_lsdb.end()) {
+ auto lsaPtr = *lsaIt;
+ NLSR_LOG_DEBUG("Removing " << lsaType << " LSA:");
+ NLSR_LOG_DEBUG(lsaPtr->toString());
+ // If the requested name LSA is not ours, we also need to remove
+ // its entries from the NPT.
+ if (lsaPtr->getOriginRouter() != m_thisRouterPrefix) {
+ m_namePrefixTable.removeEntry(lsaPtr->getOriginRouter(), lsaPtr->getOriginRouter());
+
+ if (lsaType == Lsa::Type::NAME) {
+ auto nlsaPtr = std::static_pointer_cast<NameLsa>(lsaPtr);
+ for (const auto& name : nlsaPtr->getNpl().getNames()) {
+ if (name != m_thisRouterPrefix) {
+ m_namePrefixTable.removeEntry(name, nlsaPtr->getOriginRouter());
+ }
+ }
+ }
+ }
+ m_lsdb.erase(lsaIt);
+ return true;
+ }
+ return false;
+}
+
void
Lsdb::buildAdjLsa()
{
- NLSR_LOG_TRACE("Lsdb::buildAdjLsa called");
+ NLSR_LOG_TRACE("buildAdjLsa called");
m_isBuildAdjLsaSheduled = false;
@@ -626,11 +382,8 @@
// routers to delete it, too.
else {
NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
- // Get this router's key
- ndn::Name key = m_confParam.getRouterPrefix();
- key.append(boost::lexical_cast<std::string>(Lsa::Type::ADJACENCY));
- removeAdjLsa(key);
+ removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
// Recompute routing table after removal
m_routingTable.scheduleRoutingTableCalculation();
}
@@ -651,303 +404,57 @@
}
}
-bool
-Lsdb::addAdjLsa(AdjLsa& alsa)
-{
- auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
- std::bind(adjLsaCompareByKey, _1, alsa.getKey()));
- if (it == m_adjLsdb.end()) {
- m_adjLsdb.push_back(alsa);
- // Add any new name prefixes to the NPT
- // Only add NPT entries if this is an adj LSA from another router.
- if (alsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- // Pass the originating router as both the name to register and
- // where it came from.
- m_namePrefixTable.addEntry(alsa.getOriginRouter(), alsa.getOriginRouter());
- }
- return true;
- }
- return false;
-}
-
-AdjLsa*
-Lsdb::findAdjLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
- std::bind(adjLsaCompareByKey, _1, key));
- if (it != m_adjLsdb.end()) {
- return &*it;
- }
- return nullptr;
-}
-
-bool
-Lsdb::isAdjLsaNew(const ndn::Name& key, uint64_t seqNo)
-{
- AdjLsa* adjLsaCheck = findAdjLsa(key);
- // If it is in the LSDB
- if (adjLsaCheck != nullptr) {
- // And the supplied seq no is newer (higher) than the current one.
- if (adjLsaCheck->getSeqNo() < seqNo) {
- return true;
- }
- else {
- return false;
- }
- }
- return true;
-}
-
-ndn::scheduler::EventId
-Lsdb::scheduleAdjLsaExpiration(const ndn::Name& key, int seqNo,
- const ndn::time::seconds& expTime)
-{
- return m_scheduler.schedule(expTime + GRACE_PERIOD,
- std::bind(&Lsdb::expireOrRefreshAdjLsa, this, key, seqNo));
-}
-
-bool
-Lsdb::installAdjLsa(AdjLsa& alsa)
-{
- ndn::time::seconds timeToExpire = m_lsaRefreshTime;
- AdjLsa* chkAdjLsa = findAdjLsa(alsa.getKey());
- // If this adj. LSA is not in the LSDB already
- if (chkAdjLsa == nullptr) {
- NLSR_LOG_DEBUG("New Adj LSA. Adding to LSDB");
- NLSR_LOG_DEBUG("Adding Adj Lsa");
- NLSR_LOG_DEBUG(alsa);
- addAdjLsa(alsa);
-
- m_routingTable.scheduleRoutingTableCalculation();
- if (alsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- ndn::time::system_clock::Duration duration = alsa.getExpirationTimePoint() -
- ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
- scheduleAdjLsaExpiration(alsa.getKey(), alsa.getSeqNo(), timeToExpire);
- }
- else {
- if (chkAdjLsa->getSeqNo() < alsa.getSeqNo()) {
- NLSR_LOG_DEBUG("Updated Adj LSA. Updating LSDB");
- NLSR_LOG_DEBUG("Deleting Adj Lsa");
- NLSR_LOG_DEBUG(chkAdjLsa);
- chkAdjLsa->setSeqNo(alsa.getSeqNo());
- chkAdjLsa->setExpirationTimePoint(alsa.getExpirationTimePoint());
- // If the new adj LSA has new content, update the contents of
- // the LSDB entry. Additionally, since we've changed the
- // contents of the LSDB, we have to schedule a routing
- // calculation.
- if (!chkAdjLsa->isEqualContent(alsa)) {
- chkAdjLsa->resetAdl();
- for (const auto& adjacent : alsa.getAdl()) {
- chkAdjLsa->addAdjacent(adjacent);
- }
- m_routingTable.scheduleRoutingTableCalculation();
- }
- if (alsa.getOriginRouter() != m_confParam.getRouterPrefix()) {
- auto duration = alsa.getExpirationTimePoint() - ndn::time::system_clock::now();
- timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
- }
- chkAdjLsa->getExpiringEventId().cancel();
- chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(alsa.getKey(),
- alsa.getSeqNo(),
- timeToExpire));
- NLSR_LOG_DEBUG("Adding Adj Lsa");
- NLSR_LOG_DEBUG(chkAdjLsa);
- }
- }
- return true;
-}
-
-bool
+void
Lsdb::buildAndInstallOwnAdjLsa()
{
- AdjLsa adjLsa(m_confParam.getRouterPrefix(),
- m_sequencingManager.getAdjLsaSeq() + 1,
+ AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
getLsaExpirationTimePoint(),
m_confParam.getAdjacencyList().getNumOfActiveNeighbor(),
m_confParam.getAdjacencyList());
+ m_sequencingManager.increaseAdjLsaSeq();
+ m_sequencingManager.writeSeqNoToFile();
//Sync adjacency LSAs if link-state or dry-run HR is enabled.
if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
- m_sequencingManager.increaseAdjLsaSeq();
- m_sequencingManager.writeSeqNoToFile();
m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
}
- return installAdjLsa(adjLsa);
+ installLsa(std::make_shared<AdjLsa>(adjLsa));
}
-bool
-Lsdb::removeAdjLsa(const ndn::Name& key)
-{
- auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
- std::bind(adjLsaCompareByKey, _1, key));
- if (it != m_adjLsdb.end()) {
- NLSR_LOG_DEBUG("Deleting Adj Lsa");
- NLSR_LOG_DEBUG(*it);
- if (it->getOriginRouter() != m_confParam.getRouterPrefix()) {
- m_namePrefixTable.removeEntry(it->getOriginRouter(), it->getOriginRouter());
- }
- m_adjLsdb.erase(it);
- return true;
- }
- return false;
-}
-
-bool
-Lsdb::doesAdjLsaExist(const ndn::Name& key)
-{
- auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
- std::bind(adjLsaCompareByKey, _1, key));
- return it != m_adjLsdb.end();
-}
-
-const std::list<AdjLsa>&
-Lsdb::getAdjLsdb() const
-{
- return m_adjLsdb;
-}
-
- // This function determines whether a name LSA should be refreshed
- // or expired. The conditions for getting refreshed are: it is still
- // in the LSDB, it hasn't been updated by something else already (as
- // evidenced by its seq. no.), and this is the originating router for
- // the LSA. Is it let expire in all other cases.
- // lsaKey is the key of the LSA's publishing router.
- // seqNo is the seq. no. of the candidate LSA.
void
-Lsdb::expireOrRefreshNameLsa(const ndn::Name& lsaKey, uint64_t seqNo)
+Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
{
- NLSR_LOG_DEBUG("Lsdb::expireOrRefreshNameLsa Called");
- NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
- NameLsa* chkNameLsa = findNameLsa(lsaKey);
+ NLSR_LOG_DEBUG("ExpireOrRefreshLsa called for " << lsa->getType());
+ NLSR_LOG_DEBUG("OriginRouter: " << lsa->getOriginRouter() << " Seq No: " << lsa->getSeqNo());
+
+ auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
+
// If this name LSA exists in the LSDB
- if (chkNameLsa != nullptr) {
- NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkNameLsa->getSeqNo());
+ if (lsaIt != m_lsdb.end()) {
+ auto lsaPtr = *lsaIt;
+ NLSR_LOG_DEBUG(lsaPtr->toString());
+ NLSR_LOG_DEBUG("LSA Exists with seq no: " << lsaPtr->getSeqNo());
// If its seq no is the one we are expecting.
- if (chkNameLsa->getSeqNo() == seqNo) {
- if (chkNameLsa->getOriginRouter() == m_thisRouterPrefix) {
- NLSR_LOG_DEBUG("Own Name LSA, so refreshing it");
- NLSR_LOG_DEBUG("Deleting Name Lsa");
- NLSR_LOG_DEBUG(chkNameLsa);
- chkNameLsa->setSeqNo(chkNameLsa->getSeqNo() + 1);
- m_sequencingManager.setNameLsaSeq(chkNameLsa->getSeqNo());
- chkNameLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
- NLSR_LOG_DEBUG("Adding Name Lsa");
- NLSR_LOG_DEBUG(chkNameLsa);
+ if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
+ if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
+ NLSR_LOG_DEBUG("Own " << lsaPtr->getType() << " LSA, so refreshing it.");
+ NLSR_LOG_DEBUG("Current LSA:");
+ NLSR_LOG_DEBUG(lsaPtr->toString());
+ lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
+ m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
+ lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
+ NLSR_LOG_DEBUG("Updated LSA:");
+ NLSR_LOG_DEBUG(lsaPtr->toString());
// schedule refreshing event again
- chkNameLsa->setExpiringEventId(scheduleNameLsaExpiration(chkNameLsa->getKey(),
- chkNameLsa->getSeqNo(),
- m_lsaRefreshTime));
+ lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
m_sequencingManager.writeSeqNoToFile();
- m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
+ m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
}
// Since we cannot refresh other router's LSAs, our only choice is to expire.
else {
- NLSR_LOG_DEBUG("Other's Name LSA, so removing from LSDB");
- removeNameLsa(lsaKey);
- }
- }
- }
-}
-
- // This function determines whether an adj. LSA should be refreshed
- // or expired. The conditions for getting refreshed are: it is still
- // in the LSDB, it hasn't been updated by something else already (as
- // evidenced by its seq. no.), and this is the originating router for
- // the LSA. Is it let expire in all other cases.
- // lsaKey is the key of the LSA's publishing router.
- // seqNo is the seq. no. of the candidate LSA.
-void
-Lsdb::expireOrRefreshAdjLsa(const ndn::Name& lsaKey, uint64_t seqNo)
-{
- NLSR_LOG_DEBUG("Lsdb::expireOrRefreshAdjLsa Called");
- NLSR_LOG_DEBUG("LSA Key: " << lsaKey << " Seq No: " << seqNo);
- AdjLsa* chkAdjLsa = findAdjLsa(lsaKey);
- // If this is a valid LSA
- if (chkAdjLsa != nullptr) {
- NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkAdjLsa->getSeqNo());
- // And if it hasn't been updated for some other reason
- if (chkAdjLsa->getSeqNo() == seqNo) {
- // If it is our own LSA
- if (chkAdjLsa->getOriginRouter() == m_thisRouterPrefix) {
- NLSR_LOG_DEBUG("Own Adj LSA, so refreshing it");
- NLSR_LOG_DEBUG("Deleting Adj Lsa");
- NLSR_LOG_DEBUG(chkAdjLsa);
- chkAdjLsa->setSeqNo(chkAdjLsa->getSeqNo() + 1);
- m_sequencingManager.setAdjLsaSeq(chkAdjLsa->getSeqNo());
- chkAdjLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
- NLSR_LOG_DEBUG("Adding Adj Lsa");
- NLSR_LOG_DEBUG(chkAdjLsa);
- // schedule refreshing event again
- chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(chkAdjLsa->getKey(),
- chkAdjLsa->getSeqNo(),
- m_lsaRefreshTime));
- m_sequencingManager.writeSeqNoToFile();
- m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
- }
- // An LSA from another router is expiring
- else {
- NLSR_LOG_DEBUG("Other's Adj LSA, so removing from LSDB");
- removeAdjLsa(lsaKey);
- }
- // We have changed the contents of the LSDB, so we have to
- // schedule a routing calculation
- m_routingTable.scheduleRoutingTableCalculation();
- }
- }
-}
-
- // This function determines whether an adj. LSA should be refreshed
- // or expired. The conditions for getting refreshed are: it is still
- // in the LSDB, it hasn't been updated by something else already (as
- // evidenced by its seq. no.), and this is the originating router for
- // the LSA. It is let expire in all other cases.
- // lsaKey is the key of the LSA's publishing router.
- // seqNo is the seq. no. of the candidate LSA.
-void
-Lsdb::expireOrRefreshCoordinateLsa(const ndn::Name& lsaKey,
- uint64_t seqNo)
-{
- NLSR_LOG_DEBUG("Lsdb::expireOrRefreshCorLsa Called ");
- NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
- CoordinateLsa* chkCorLsa = findCoordinateLsa(lsaKey);
- // Whether the LSA is in the LSDB or not.
- if (chkCorLsa != nullptr) {
- NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkCorLsa->getSeqNo());
- // Whether the LSA has been updated without our knowledge.
- if (chkCorLsa->getSeqNo() == seqNo) {
- if (chkCorLsa->getOriginRouter() == m_thisRouterPrefix) {
- NLSR_LOG_DEBUG("Own Cor LSA, so refreshing it");
- NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
- NLSR_LOG_DEBUG(chkCorLsa);
- chkCorLsa->setSeqNo(chkCorLsa->getSeqNo() + 1);
- if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- m_sequencingManager.setCorLsaSeq(chkCorLsa->getSeqNo());
- }
-
- chkCorLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
- NLSR_LOG_DEBUG("Adding Coordinate Lsa");
- NLSR_LOG_DEBUG(chkCorLsa);
- // schedule refreshing event again
- chkCorLsa->setExpiringEventId(scheduleCoordinateLsaExpiration(
- chkCorLsa->getKey(),
- chkCorLsa->getSeqNo(),
- m_lsaRefreshTime));
- // Only sync coordinate LSAs if link-state routing is disabled
- if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- m_sequencingManager.writeSeqNoToFile();
- m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
- }
- }
- // We can't refresh other router's LSAs, so we remove it.
- else {
- NLSR_LOG_DEBUG("Other's Cor LSA, so removing from LSDB");
- removeCoordinateLsa(lsaKey);
- }
- if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
- m_routingTable.scheduleRoutingTableCalculation();
+ NLSR_LOG_DEBUG("Other's " << lsaPtr->getType() << " LSA, so removing from LSDB");
+ removeLsa(lsaPtr->getOriginRouter(), lsaPtr->getType());
}
}
}
@@ -1015,281 +522,99 @@
m_fetchers.erase(it);
});
- // increment a specific SENT_LSA_INTEREST
Lsa::Type lsaType;
std::istringstream(interestName[-2].toUri()) >> lsaType;
- switch (lsaType) {
- case Lsa::Type::ADJACENCY:
- lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
- break;
- case Lsa::Type::COORDINATE:
- lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
- break;
- case Lsa::Type::NAME:
- lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
- break;
- default:
- NLSR_LOG_ERROR("lsaType " << lsaType << " not recognized; failed Statistics::PacketType conversion");
+ incrementInterestSentStats(lsaType);
+}
+
+void
+Lsdb::onFetchLsaError(uint32_t errorCode, const std::string& msg, const ndn::Name& interestName,
+ uint32_t retransmitNo, const ndn::time::steady_clock::TimePoint& deadline,
+ ndn::Name lsaName, uint64_t seqNo)
+{
+ NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
+ << ", Message: " << msg);
+
+ if (ndn::time::steady_clock::now() < deadline) {
+ auto it = m_highestSeqNo.find(lsaName);
+ if (it != m_highestSeqNo.end() && it->second == seqNo) {
+ // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
+ // immediately since at the least the LSA Interest lifetime has elapsed.
+ // Otherwise, it is necessary to delay the Interest re-expression to prevent
+ // the potential for constant Interest flooding.
+ ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
+
+ if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
+ delay = ndn::time::seconds(0);
+ }
+ m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
+ interestName, retransmitNo + 1, deadline));
+ }
}
}
void
-Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
+Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
{
- ndn::Name interestName(interest.getName());
- NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
+ NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
+ lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
- if (interestName[-2].isVersion()) {
- // Interest for particular segment
- if (m_segmentPublisher.replyFromStore(interestName)) {
- NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
- return;
- }
- // Remove version and segment
- interestName = interestName.getSubName(0, interestName.size() - 2);
- NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
+ ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
+ uint64_t seqNo = interestName[-1].toNumber();
+
+ if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
+ m_highestSeqNo[lsaName] = seqNo;
}
-
- // increment RCV_LSA_INTEREST
- lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
+ else if (seqNo > m_highestSeqNo[lsaName]) {
+ m_highestSeqNo[lsaName] = seqNo;
+ NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
+ }
+ else if (seqNo < m_highestSeqNo[lsaName]) {
+ return;
+ }
std::string chkString("LSA");
int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
- // Forms the name of the router that the Interest packet came from.
- ndn::Name originRouter = m_confParam.getNetwork();
- originRouter.append(interestName.getSubName(lsaPosition + 1,
- interestName.size() - lsaPosition - 3));
+ if (lsaPosition >= 0) {
+ // Extracts the prefix of the originating router from the data.
+ ndn::Name originRouter = m_confParam.getNetwork();
+ originRouter.append(interestName.getSubName(lsaPosition + 1,
+ interestName.size() - lsaPosition - 3));
- // if the interest is for this router's LSA
- if (originRouter == m_confParam.getRouterPrefix() && lsaPosition >= 0) {
- uint64_t seqNo = interestName[-1].toNumber();
- NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
+ try {
+ Lsa::Type interestedLsType;
+ std::istringstream(interestName[-2].toUri()) >> interestedLsType;
- std::string lsaType = interestName[-2].toUri();
- Lsa::Type interestedLsType;
- std::istringstream(lsaType) >> interestedLsType;
+ if (interestedLsType == Lsa::Type::BASE) {
+ NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestName[-2].toUri());
+ return;
+ }
- if (interestedLsType == Lsa::Type::NAME) {
- processInterestForNameLsa(interest, originRouter.append(lsaType), seqNo);
+ ndn::Block block(bufferPtr);
+ if (interestedLsType == Lsa::Type::NAME) {
+ lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
+ if (isLsaNew(originRouter, interestedLsType, seqNo)) {
+ installLsa(std::make_shared<NameLsa>(block));
+ }
+ }
+ else if (interestedLsType == Lsa::Type::ADJACENCY) {
+ lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
+ if (isLsaNew(originRouter, interestedLsType, seqNo)) {
+ installLsa(std::make_shared<AdjLsa>(block));
+ }
+ }
+ else if (interestedLsType == Lsa::Type::COORDINATE) {
+ lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
+ if (isLsaNew(originRouter, interestedLsType, seqNo)) {
+ installLsa(std::make_shared<CoordinateLsa>(block));
+ }
+ }
}
- else if (interestedLsType == Lsa::Type::ADJACENCY) {
- processInterestForAdjacencyLsa(interest, originRouter.append(lsaType), seqNo);
+ catch (const std::exception& e) {
+ NLSR_LOG_TRACE("LSA data decoding error :( " << e.what());
+ return;
}
- else if (interestedLsType == Lsa::Type::COORDINATE) {
- processInterestForCoordinateLsa(interest, originRouter.append(lsaType), seqNo);
- }
- else {
- NLSR_LOG_WARN("Received unrecognized LSA type: " << interestedLsType);
- }
- lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
- }
- else { // else the interest is for other router's lsa, serve from LsaSegmentStorage
- std::shared_ptr<const ndn::Data> lsaSegment = m_lsaStorage.find(interest);
- if (lsaSegment) {
- NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
- m_face.put(*lsaSegment);
- }
- else {
- NLSR_LOG_TRACE(interest << " was not found in this lsa storage.");
- }
- }
-}
-
- // \brief Finds and sends a requested name LSA.
- // \param interest The interest that seeks the name LSA.
- // \param lsaKey The LSA that the Interest is seeking.
- // \param seqNo A sequence number to ensure that we are sending the
- // version that was requested.
-void
-Lsdb::processInterestForNameLsa(const ndn::Interest& interest,
- const ndn::Name& lsaKey,
- uint64_t seqNo)
-{
- // increment RCV_NAME_LSA_INTEREST
- lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
- NLSR_LOG_DEBUG("nameLsa interest " << interest << " received");
- NameLsa* nameLsa = findNameLsa(lsaKey);
- if (nameLsa != nullptr) {
- NLSR_LOG_TRACE("Verifying SeqNo for NameLsa is same as requested.");
- if (nameLsa->getSeqNo() == seqNo) {
- m_segmentPublisher.publish(interest.getName(), interest.getName(),
- nameLsa->wireEncode(),
- m_lsaRefreshTime, m_confParam.getSigningInfo());
-
- lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
- }
- else {
- NLSR_LOG_TRACE("SeqNo for nameLsa does not match");
- }
- }
- else {
- NLSR_LOG_TRACE(interest << " was not found in this lsdb");
- }
-}
-
- // \brief Finds and sends a requested adj. LSA.
- // \param interest The interest that seeks the adj. LSA.
- // \param lsaKey The LSA that the Interest is seeking.
- // \param seqNo A sequence number to ensure that we are sending the
- // version that was requested.
-void
-Lsdb::processInterestForAdjacencyLsa(const ndn::Interest& interest,
- const ndn::Name& lsaKey,
- uint64_t seqNo)
-{
- if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
- NLSR_LOG_ERROR("Received interest for an adjacency LSA when hyperbolic routing is enabled");
- }
-
- lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
- NLSR_LOG_DEBUG("AdjLsa interest " << interest << " received");
- AdjLsa* adjLsa = findAdjLsa(lsaKey);
- if (adjLsa != nullptr) {
- NLSR_LOG_TRACE("Verifying SeqNo for AdjLsa is same as requested.");
- if (adjLsa->getSeqNo() == seqNo) {
- m_segmentPublisher.publish(interest.getName(), interest.getName(),
- adjLsa->wireEncode(),
- m_lsaRefreshTime, m_confParam.getSigningInfo());
-
- lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
- }
- else {
- NLSR_LOG_TRACE("SeqNo for AdjLsa does not match");
- }
- }
- else {
- NLSR_LOG_TRACE(interest << " was not found in this lsdb");
- }
-}
-
- // \brief Finds and sends a requested cor. LSA.
- // \param interest The interest that seeks the cor. LSA.
- // \param lsaKey The LSA that the Interest is seeking.
- // \param seqNo A sequence number to ensure that we are sending the
- // version that was requested.
-void
-Lsdb::processInterestForCoordinateLsa(const ndn::Interest& interest,
- const ndn::Name& lsaKey,
- uint64_t seqNo)
-{
- if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
- NLSR_LOG_ERROR("Received Interest for a coordinate LSA when link-state routing is enabled");
- }
-
- lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
- NLSR_LOG_DEBUG("CoordinateLsa interest " << interest << " received");
- CoordinateLsa* corLsa = findCoordinateLsa(lsaKey);
- if (corLsa != nullptr) {
- NLSR_LOG_TRACE("Verifying SeqNo for CoordinateLsa is same as requested.");
- if (corLsa->getSeqNo() == seqNo) {
- m_segmentPublisher.publish(interest.getName(), interest.getName(),
- corLsa->wireEncode(),
- m_lsaRefreshTime, m_confParam.getSigningInfo());
-
- lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
- }
- else {
- NLSR_LOG_TRACE("SeqNo for CoordinateLsa does not match");
- }
- }
- else {
- NLSR_LOG_TRACE(interest << " was not found in this lsdb");
- }
-}
-
-void
-Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
- uint64_t lsSeqNo, const ndn::Block& block)
-{
- lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
- if (isNameLsaNew(lsaKey, lsSeqNo)) {
- NameLsa nameLsa(block);
- installNameLsa(nameLsa);
- }
-}
-
-void
-Lsdb::processContentAdjacencyLsa(const ndn::Name& lsaKey,
- uint64_t lsSeqNo, const ndn::Block& block)
-{
- lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
- if (isAdjLsaNew(lsaKey, lsSeqNo)) {
- AdjLsa adjLsa(block);
- installAdjLsa(adjLsa);
- }
-}
-
-void
-Lsdb::processContentCoordinateLsa(const ndn::Name& lsaKey,
- uint64_t lsSeqNo, const ndn::Block& block)
-{
- lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
- if (isCoordinateLsaNew(lsaKey, lsSeqNo)) {
- CoordinateLsa corLsa(block);
- installCoordinateLsa(corLsa);
- }
-}
-
-ndn::time::system_clock::TimePoint
-Lsdb::getLsaExpirationTimePoint()
-{
- ndn::time::system_clock::TimePoint expirationTimePoint = ndn::time::system_clock::now();
- expirationTimePoint = expirationTimePoint +
- ndn::time::seconds(m_confParam.getRouterDeadInterval());
- return expirationTimePoint;
-}
-
-void
-Lsdb::writeAdjLsdbLog()
-{
- if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
- return;
- }
-
- NLSR_LOG_TRACE("---------------Adj LSDB-------------------");
- for (const auto& adj : m_adjLsdb) {
- NLSR_LOG_TRACE(adj);
- }
-}
-
-//-----utility function -----
-bool
-Lsdb::doesLsaExist(const ndn::Name& key, const Lsa::Type& lsType)
-{
- switch (lsType) {
- case Lsa::Type::ADJACENCY:
- return doesAdjLsaExist(key);
-
- case Lsa::Type::COORDINATE:
- return doesCoordinateLsaExist(key);
-
- case Lsa::Type::NAME:
- return doesNameLsaExist(key);
-
- default:
- return false;
- }
-}
-
-bool
-Lsdb::isLsaNew(const ndn::Name& routerName, const Lsa::Type& lsaType,
- const uint64_t& sequenceNumber) {
- ndn::Name lsaKey = routerName;
- lsaKey.append(boost::lexical_cast<std::string>(lsaType));
-
- switch (lsaType) {
- case Lsa::Type::ADJACENCY:
- return isAdjLsaNew(lsaKey, sequenceNumber);
-
- case Lsa::Type::COORDINATE:
- return isCoordinateLsaNew(lsaKey, sequenceNumber);
-
- case Lsa::Type::NAME:
- return isNameLsaNew(lsaKey, sequenceNumber);
-
- default:
- return false;
}
}