28#include <ndn-cxx/lp/tags.hpp>
36 , m_scheduler(face.getIoContext())
37 , m_confParam(confParam)
38 , m_sync(m_face, keyChain,
40 confParam.getSyncProtocol(),
41 confParam.getSyncPrefix(),
42 confParam.getSyncUserPrefix(),
43 confParam.getSyncInterestLifetime(),
44 confParam.getRouterPrefix(),
45 confParam.getHyperbolicState()
47 , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
48 , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
49 , m_thisRouterPrefix(m_confParam.getRouterPrefix())
50 , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
51 , m_onSyncUpdate(m_sync.onSyncUpdate.connect(
52 [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
53 const ndn::Name& originRouter, uint64_t incomingFaceId) {
54 processUpdateFromSync(updateName, sequenceNumber, originRouter, incomingFaceId);
56 , m_segmenter(keyChain, m_confParam.getSigningInfo())
58 , m_isBuildAdjLsaScheduled(
false)
61 ndn::Name name = m_confParam.getLsaPrefix();
64 m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(
false),
65 [
this] (
const auto& name,
const auto& interest) { processInterest(name, interest); },
66 [] (
const auto& name) {
NLSR_LOG_DEBUG(
"Successfully registered prefix: " << name); },
67 [] (
const auto& name,
const auto& reason) {
69 NDN_THROW(std::runtime_error(
"Register prefix failed: " + reason));
71 m_confParam.getSigningInfo(), ndn::nfd::ROUTE_FLAG_CAPTURE);
73 buildAndInstallOwnNameLsa();
76 buildAndInstallOwnCoordinateLsa();
82 for (
const auto& fetcher : m_fetchers) {
88Lsdb::processUpdateFromSync(
const ndn::Name& updateName, uint64_t seqNo,
89 const ndn::Name& originRouter, uint64_t incomingFaceId)
91 NLSR_LOG_DEBUG(
"Origin Router of update: " << originRouter <<
" seq: " << seqNo);
92 auto lsaType = boost::lexical_cast<Lsa::Type>(updateName.get(-1).toUri());
94 if (originRouter == m_thisRouterPrefix) {
99 if (isLsaNew(originRouter, lsaType, seqNo)) {
107 buildAndInstallOwnAdjLsa();
112 buildAndInstallOwnCoordinateLsa();
119 NLSR_LOG_DEBUG(
"Received sync update with higher " << lsaType <<
" sequence number than entry in LSDB");
121 if (isLsaNew(originRouter, lsaType, seqNo)) {
124 NLSR_LOG_ERROR(
"Got an update for adjacency LSA when hyperbolic routing "
125 "is enabled. Not going to fetch.");
131 NLSR_LOG_ERROR(
"Got an update for coordinate LSA when link-state "
132 "is enabled. Not going to fetch.");
136 onNewLsa(updateName, seqNo, originRouter, incomingFaceId);
138 ndn::Name lsaInterest{updateName};
139 lsaInterest.appendNumber(seqNo);
140 expressInterest(lsaInterest, 0, incomingFaceId);
153 installLsa(std::make_shared<NameLsa>(nameLsa));
157Lsdb::buildAndInstallOwnCoordinateLsa()
160 getLsaExpirationTimePoint(), m_confParam.
getCorR(),
170 installLsa(std::make_shared<CoordinateLsa>(corLsa));
180 NLSR_LOG_DEBUG(
"Adjacency LSA not built while in hyperbolic routing state");
184 if (m_isBuildAdjLsaScheduled) {
185 NLSR_LOG_DEBUG(
"Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
188 NLSR_LOG_DEBUG(
"Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
189 m_isBuildAdjLsaScheduled =
true;
191 m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [
this] { buildAdjLsa(); });
205 NLSR_LOG_DEBUG(
"---------------" << type <<
" LSDB-------------------");
206 auto lsaRange = m_lsdb.get<
byType>().equal_range(type);
207 for (
auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
216 ndn::Name interestName(interest.getName());
219 if (interestName[-2].isVersion()) {
221 auto data = m_segmentFifo.find(interestName);
229 interestName = interestName.getPrefix(-2);
230 NLSR_LOG_TRACE(
"Interest w/o segment and version: " << interestName);
236 std::string chkString(
"LSA");
240 ndn::Name originRouter = m_confParam.
getNetwork();
241 originRouter.append(interestName.getSubName(lsaPosition + 1,
242 interestName.size() - lsaPosition - 3));
245 if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
246 uint64_t seqNo = interestName[-1].toNumber();
249 std::string lsaType = interestName[-2].toUri();
251 std::istringstream(lsaType) >> interestedLsType;
253 NLSR_LOG_WARN(
"Received unrecognized LSA type: " << lsaType);
257 incrementInterestRcvdStats(interestedLsType);
258 if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
263 else if (
auto lsaSegment = m_lsaStorage.find(interest); lsaSegment) {
264 NLSR_LOG_TRACE(
"Found data in LSA storage. Sending data for " << interest.getName());
265 m_face.put(*lsaSegment);
270Lsdb::processInterestForLsa(
const ndn::Interest& interest,
const ndn::Name& originRouter,
275 if (
auto lsaPtr =
findLsa(originRouter, lsaType); lsaPtr) {
276 NLSR_LOG_TRACE(
"Verifying SeqNo for " << lsaType <<
" is same as requested");
277 if (lsaPtr->getSeqNo() == seqNo) {
278 auto segments = m_segmenter.segment(lsaPtr->wireEncode(),
279 ndn::Name(interest.getName()).appendVersion(),
280 ndn::MAX_NDN_PACKET_SIZE / 2, m_lsaRefreshTime);
281 for (
const auto& data : segments) {
282 m_segmentFifo.insert(*data, m_lsaRefreshTime);
283 m_scheduler.schedule(m_lsaRefreshTime,
284 [
this, name = data->getName()] { m_segmentFifo.erase(name); });
288 if (interest.getName()[-1].isSegment()) {
289 segNum = interest.getName()[-1].toSegment();
291 if (segNum < segments.size()) {
292 m_face.put(*segments[segNum]);
294 incrementDataSentStats(lsaType);
305Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
307 auto timeToExpire = m_lsaRefreshTime;
308 if (lsa->getOriginRouter() != m_thisRouterPrefix) {
309 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
310 if (duration > ndn::time::seconds(0)) {
311 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
315 auto chkLsa =
findLsa(lsa->getOriginRouter(), lsa->getType());
316 if (chkLsa ==
nullptr) {
322 lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
325 else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
327 chkLsa->setSeqNo(lsa->getSeqNo());
328 chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
330 auto [updated, namesToAdd, namesToRemove] = chkLsa->update(lsa);
335 chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
341Lsdb::removeLsa(
const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt)
343 if (lsaIt != m_lsdb.end()) {
344 auto lsaPtr = *lsaIt;
352Lsdb::removeLsa(
const ndn::Name& router,
Lsa::Type lsaType)
354 removeLsa(m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)));
362 m_isBuildAdjLsaScheduled =
false;
366 int adjBuildCount = m_adjBuildCount;
368 if (adjBuildCount > 0) {
372 buildAndInstallOwnAdjLsa();
385 m_adjBuildCount = m_adjBuildCount - adjBuildCount;
392 m_isBuildAdjLsaScheduled =
true;
395 m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [
this] { buildAdjLsa(); });
400Lsdb::buildAndInstallOwnAdjLsa()
402 AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.
getAdjLsaSeq() + 1,
403 getLsaExpirationTimePoint(),
413 installLsa(std::make_shared<AdjLsa>(adjLsa));
416ndn::scheduler::EventId
417Lsdb::scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
420 return m_scheduler.schedule(expTime +
GRACE_PERIOD, [
this, lsa] { expireOrRefreshLsa(lsa); });
424Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
426 NLSR_LOG_DEBUG(
"ExpireOrRefreshLsa called for " << lsa->getType());
427 NLSR_LOG_DEBUG(
"OriginRouter: " << lsa->getOriginRouter() <<
" Seq No: " << lsa->getSeqNo());
429 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
432 if (lsaIt != m_lsdb.end()) {
433 auto lsaPtr = *lsaIt;
437 if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
438 if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
439 NLSR_LOG_DEBUG(
"Own " << lsaPtr->getType() <<
" LSA, so refreshing it");
441 lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
442 m_sequencingManager.
setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
443 lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
446 lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
452 NLSR_LOG_DEBUG(
"Other's " << lsaPtr->getType() <<
" LSA, so removing from LSDB");
460Lsdb::expressInterest(
const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
461 ndn::time::steady_clock::time_point deadline)
466 if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
467 deadline = ndn::time::steady_clock::now() + ndn::time::seconds(
static_cast<int>(
LSA_REFRESH_TIME_MAX));
470 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
472 uint64_t seqNo = interestName[-1].toNumber();
475 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
476 m_highestSeqNo[lsaName] = seqNo;
479 else if (seqNo > m_highestSeqNo[lsaName]) {
480 m_highestSeqNo[lsaName] = seqNo;
483 else if (seqNo < m_highestSeqNo[lsaName]) {
487 ndn::Interest interest(interestName);
488 if (incomingFaceId != 0) {
489 interest.setTag(std::make_shared<ndn::lp::NextHopFaceIdTag>(incomingFaceId));
491 ndn::SegmentFetcher::Options options;
495 NLSR_LOG_DEBUG(
"Fetching Data for LSA: " << interestName <<
" Seq number: " << seqNo);
496 auto fetcher = ndn::SegmentFetcher::start(m_face, interest, m_confParam.
getValidator(), options);
498 auto it = m_fetchers.insert(fetcher).first;
500 fetcher->afterSegmentValidated.connect([
this] (
const ndn::Data& data) {
505 auto lsaSegment = std::make_shared<const ndn::Data>(data);
506 m_lsaStorage.insert(*lsaSegment);
509 [
this, name = lsaSegment->getName()] { m_lsaStorage.erase(name); });
512 fetcher->onComplete.connect([=] (
const ndn::ConstBufferPtr& bufferPtr) {
513 m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
514 afterFetchLsa(bufferPtr, interestName);
515 m_fetchers.erase(it);
518 fetcher->onError.connect([=] (uint32_t errorCode,
const std::string& msg) {
519 onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
520 m_fetchers.erase(it);
524 std::istringstream(interestName[-2].toUri()) >> lsaType;
525 incrementInterestSentStats(lsaType);
529Lsdb::onFetchLsaError(uint32_t errorCode,
const std::string& msg,
const ndn::Name& interestName,
530 uint32_t retransmitNo,
const ndn::time::steady_clock::time_point& deadline,
531 ndn::Name lsaName, uint64_t seqNo)
533 NLSR_LOG_DEBUG(
"Failed to fetch LSA: " << lsaName <<
", Error code: " << errorCode
534 <<
", Message: " << msg);
536 if (ndn::time::steady_clock::now() < deadline) {
537 auto it = m_highestSeqNo.find(lsaName);
538 if (it != m_highestSeqNo.end() && it->second == seqNo) {
544 if (errorCode == ndn::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
547 m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest,
this, interestName,
548 retransmitNo + 1, 0, deadline));
554Lsdb::afterFetchLsa(
const ndn::ConstBufferPtr& bufferPtr,
const ndn::Name& interestName)
556 NLSR_LOG_DEBUG(
"Received data for LSA interest: " << interestName);
559 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
560 uint64_t seqNo = interestName[-1].toNumber();
562 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
563 m_highestSeqNo[lsaName] = seqNo;
565 else if (seqNo > m_highestSeqNo[lsaName]) {
566 m_highestSeqNo[lsaName] = seqNo;
567 NLSR_LOG_TRACE(
"SeqNo for LSA(name): " << interestName <<
" updated");
569 else if (seqNo < m_highestSeqNo[lsaName]) {
573 std::string chkString(
"LSA");
576 if (lsaPosition >= 0) {
578 ndn::Name originRouter = m_confParam.
getNetwork();
579 originRouter.append(interestName.getSubName(lsaPosition + 1,
580 interestName.size() - lsaPosition - 3));
583 std::istringstream(interestName[-2].toUri()) >> interestedLsType;
586 NLSR_LOG_WARN(
"Received unrecognized LSA Type: " << interestName[-2].toUri());
590 ndn::Block block(bufferPtr);
593 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
594 installLsa(std::make_shared<NameLsa>(block));
599 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
600 installLsa(std::make_shared<AdjLsa>(block));
605 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
606 installLsa(std::make_shared<CoordinateLsa>(block));
610 catch (
const std::exception& e) {
int32_t getNumOfActiveNeighbor() const
bool isAdjLsaBuildable(const uint32_t interestRetryNo) const
Determines whether this list can be used to build an adj. LSA.
A class to house all the configuration parameters for NLSR.
const ndn::Name & getNetwork() const
std::vector< double > getCorTheta() const
uint32_t getInterestRetryNumber() const
uint32_t getInterestResendTime() const
NamePrefixList & getNamePrefixList()
const ndn::time::seconds & getLsaInterestLifetime() const
AdjacencyList & getAdjacencyList()
HyperbolicState getHyperbolicState() const
ndn::security::ValidatorConfig & getValidator()
Represents an LSA of hyperbolic coordinates of the origin router.
ndn::signal::Signal< Lsdb, Statistics::PacketType > lsaIncrementSignal
void buildAndInstallOwnNameLsa()
Builds a name LSA for this router and then installs it into the LSDB.
std::shared_ptr< T > findLsa(const ndn::Name &router) const
AfterLsdbModified onLsdbModified
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
ndn::signal::Signal< Lsdb, ndn::Data > afterSegmentValidatedSignal
void scheduleAdjLsaBuild()
Schedules a build of this router's LSA.
Lsdb(ndn::Face &face, ndn::KeyChain &keyChain, ConfParameter &confParam)
Represents an LSA of name prefixes announced by the origin router.
uint64_t getNameLsaSeq() const
uint64_t getLsaSeq(Lsa::Type lsaType)
void setNameLsaSeq(uint64_t nlsn)
void setLsaSeq(uint64_t seqNo, Lsa::Type lsaType)
uint64_t getAdjLsaSeq() const
uint64_t getCorLsaSeq() const
void setCorLsaSeq(uint64_t clsn)
void increaseNameLsaSeq()
void writeSeqNoToFile() const
void setAdjLsaSeq(uint64_t alsn)
void publishRoutingUpdate(Lsa::Type type, uint64_t seqNo)
Instruct ChronoSync to publish an update.
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
#define NLSR_LOG_DEBUG(x)
#define INIT_LOGGER(name)
#define NLSR_LOG_ERROR(x)
#define NLSR_LOG_TRACE(x)
int32_t getNameComponentPosition(const ndn::Name &name, const std::string &searchString)
search a name component in ndn::Name and return the position of the component
Copyright (c) 2014-2020, The University of Memphis, Regents of the University of California.
@ LSA_REFRESH_TIME_DEFAULT
constexpr ndn::time::seconds GRACE_PERIOD