28 #include <ndn-cxx/lp/tags.hpp>
36 , m_scheduler(face.getIoService())
37 , m_confParam(confParam)
38 , m_sync(m_face, keyChain,
39 [this] (const auto& routerName, const
Lsa::Type& lsaType,
40 uint64_t sequenceNumber, uint64_t incomingFaceId) {
41 return isLsaNew(routerName, lsaType, sequenceNumber);
43 , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
44 , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
45 , m_thisRouterPrefix(m_confParam.getRouterPrefix())
46 , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
47 , m_onNewLsaConnection(m_sync.onNewLsa.connect(
48 [
this] (
const ndn::Name& updateName, uint64_t sequenceNumber,
49 const ndn::Name& originRouter, uint64_t incomingFaceId) {
50 ndn::Name lsaInterest{updateName};
51 lsaInterest.appendNumber(sequenceNumber);
52 expressInterest(lsaInterest, 0, incomingFaceId);
54 , m_segmenter(keyChain, m_confParam.getSigningInfo())
56 , m_isBuildAdjLsaScheduled(
false)
59 ndn::Name name = m_confParam.getLsaPrefix();
62 m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(
false),
63 [
this] (
const auto& name,
const auto& interest) { processInterest(name, interest); },
64 [] (
const auto& name) {
NLSR_LOG_DEBUG(
"Successfully registered prefix: " << name); },
65 [] (
const auto& name,
const auto& reason) {
67 NDN_THROW(std::runtime_error(
"Register prefix failed: " + reason));
69 m_confParam.getSigningInfo(), ndn::nfd::ROUTE_FLAG_CAPTURE);
71 buildAndInstallOwnNameLsa();
74 buildAndInstallOwnCoordinateLsa();
80 for (
const auto& fetcher : m_fetchers) {
86 Lsdb::buildAndInstallOwnNameLsa()
88 NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
89 getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
90 m_sequencingManager.increaseNameLsaSeq();
91 m_sequencingManager.writeSeqNoToFile();
92 m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
94 installLsa(std::make_shared<NameLsa>(nameLsa));
98 Lsdb::buildAndInstallOwnCoordinateLsa()
100 CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
101 getLsaExpirationTimePoint(), m_confParam.getCorR(),
102 m_confParam.getCorTheta());
103 m_sequencingManager.increaseCorLsaSeq();
104 m_sequencingManager.writeSeqNoToFile();
108 m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
111 installLsa(std::make_shared<CoordinateLsa>(corLsa));
115 Lsdb::scheduleAdjLsaBuild()
121 NLSR_LOG_DEBUG(
"Adjacency LSA not built while in hyperbolic routing state");
125 if (m_isBuildAdjLsaScheduled) {
126 NLSR_LOG_DEBUG(
"Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
129 NLSR_LOG_DEBUG(
"Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
130 m_isBuildAdjLsaScheduled =
true;
132 m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [
this] { buildAdjLsa(); });
136 Lsdb::writeLog()
const
138 static const Lsa::Type types[] = {Lsa::Type::COORDINATE, Lsa::Type::NAME, Lsa::Type::ADJACENCY};
139 for (
const auto& type : types) {
140 if ((type == Lsa::Type::COORDINATE &&
142 (type == Lsa::Type::ADJACENCY &&
147 NLSR_LOG_DEBUG(
"---------------" << type <<
" LSDB-------------------");
148 auto lsaRange = m_lsdb.get<
byType>().equal_range(type);
149 for (
auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
156 Lsdb::processInterest(
const ndn::Name& name,
const ndn::Interest& interest)
158 ndn::Name interestName(interest.getName());
161 if (interestName[-2].isVersion()) {
163 auto data = m_segmentFifo.find(interestName);
171 interestName = interestName.getPrefix(-2);
172 NLSR_LOG_TRACE(
"Interest w/o segment and version: " << interestName);
176 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
178 std::string chkString(
"LSA");
182 ndn::Name originRouter = m_confParam.getNetwork();
183 originRouter.append(interestName.getSubName(lsaPosition + 1,
184 interestName.size() - lsaPosition - 3));
187 if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
188 uint64_t seqNo = interestName[-1].toNumber();
191 std::string lsaType = interestName[-2].toUri();
193 std::istringstream(lsaType) >> interestedLsType;
194 if (interestedLsType == Lsa::Type::BASE) {
195 NLSR_LOG_WARN(
"Received unrecognized LSA type: " << lsaType);
199 incrementInterestRcvdStats(interestedLsType);
200 if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
201 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
205 else if (
auto lsaSegment = m_lsaStorage.find(interest); lsaSegment) {
206 NLSR_LOG_TRACE(
"Found data in lsa storage. Sending data for " << interest.getName());
207 m_face.put(*lsaSegment);
212 Lsdb::processInterestForLsa(
const ndn::Interest& interest,
const ndn::Name& originRouter,
217 if (
auto lsaPtr = findLsa(originRouter, lsaType); lsaPtr) {
218 NLSR_LOG_TRACE(
"Verifying SeqNo for " << lsaType <<
" is same as requested");
219 if (lsaPtr->getSeqNo() == seqNo) {
220 auto segments = m_segmenter.segment(lsaPtr->wireEncode(),
221 ndn::Name(interest.getName()).appendVersion(),
222 ndn::MAX_NDN_PACKET_SIZE / 2, m_lsaRefreshTime);
223 for (
const auto& data : segments) {
224 m_segmentFifo.insert(*data, m_lsaRefreshTime);
225 m_scheduler.schedule(m_lsaRefreshTime,
226 [
this, name = data->getName()] { m_segmentFifo.erase(name); });
230 if (interest.getName()[-1].isSegment()) {
231 segNum = interest.getName()[-1].toSegment();
233 if (segNum < segments.size()) {
234 m_face.put(*segments[segNum]);
236 incrementDataSentStats(lsaType);
247 Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
249 auto timeToExpire = m_lsaRefreshTime;
250 if (lsa->getOriginRouter() != m_thisRouterPrefix) {
251 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
252 if (duration > ndn::time::seconds(0)) {
253 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
257 auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
258 if (chkLsa ==
nullptr) {
264 onLsdbModified(lsa, LsdbUpdate::INSTALLED, {}, {});
266 lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
269 else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
272 chkLsa->setSeqNo(lsa->getSeqNo());
273 chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
275 auto [updated, namesToAdd, namesToRemove] = chkLsa->update(lsa);
277 onLsdbModified(lsa, LsdbUpdate::UPDATED, namesToAdd, namesToRemove);
280 chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
287 Lsdb::removeLsa(
const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt)
289 if (lsaIt != m_lsdb.end()) {
290 auto lsaPtr = *lsaIt;
294 onLsdbModified(lsaPtr, LsdbUpdate::REMOVED, {}, {});
299 Lsdb::removeLsa(
const ndn::Name& router, Lsa::Type lsaType)
301 removeLsa(m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)));
309 m_isBuildAdjLsaScheduled =
false;
311 if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
313 int adjBuildCount = m_adjBuildCount;
315 if (adjBuildCount > 0) {
317 if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
319 buildAndInstallOwnAdjLsa();
327 removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
332 m_adjBuildCount = m_adjBuildCount - adjBuildCount;
339 m_isBuildAdjLsaScheduled =
true;
340 auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
341 m_confParam.getInterestResendTime());
342 m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [
this] { buildAdjLsa(); });
347 Lsdb::buildAndInstallOwnAdjLsa()
349 AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
350 getLsaExpirationTimePoint(),
351 m_confParam.getAdjacencyList().getNumOfActiveNeighbor(),
352 m_confParam.getAdjacencyList());
353 m_sequencingManager.increaseAdjLsaSeq();
354 m_sequencingManager.writeSeqNoToFile();
358 m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
361 installLsa(std::make_shared<AdjLsa>(adjLsa));
364 ndn::scheduler::EventId
365 Lsdb::scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
368 return m_scheduler.schedule(expTime +
GRACE_PERIOD, [
this, lsa] { expireOrRefreshLsa(lsa); });
372 Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
374 NLSR_LOG_DEBUG(
"ExpireOrRefreshLsa called for " << lsa->getType());
375 NLSR_LOG_DEBUG(
"OriginRouter: " << lsa->getOriginRouter() <<
" Seq No: " << lsa->getSeqNo());
377 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
380 if (lsaIt != m_lsdb.end()) {
381 auto lsaPtr = *lsaIt;
385 if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
386 if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
387 NLSR_LOG_DEBUG(
"Own " << lsaPtr->getType() <<
" LSA, so refreshing it");
390 lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
391 m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
392 lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
396 lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
397 m_sequencingManager.writeSeqNoToFile();
398 m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
402 NLSR_LOG_DEBUG(
"Other's " << lsaPtr->getType() <<
" LSA, so removing from LSDB");
410 Lsdb::expressInterest(
const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
411 ndn::time::steady_clock::time_point deadline)
414 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
416 if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
417 deadline = ndn::time::steady_clock::now() + ndn::time::seconds(
static_cast<int>(
LSA_REFRESH_TIME_MAX));
420 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
422 uint64_t seqNo = interestName[-1].toNumber();
425 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
426 m_highestSeqNo[lsaName] = seqNo;
429 else if (seqNo > m_highestSeqNo[lsaName]) {
430 m_highestSeqNo[lsaName] = seqNo;
433 else if (seqNo < m_highestSeqNo[lsaName]) {
437 ndn::Interest interest(interestName);
438 if (incomingFaceId != 0) {
439 interest.setTag(std::make_shared<ndn::lp::NextHopFaceIdTag>(incomingFaceId));
441 ndn::util::SegmentFetcher::Options options;
442 options.interestLifetime = m_confParam.getLsaInterestLifetime();
443 options.maxTimeout = m_confParam.getLsaInterestLifetime();
445 NLSR_LOG_DEBUG(
"Fetching Data for LSA: " << interestName <<
" Seq number: " << seqNo);
446 auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
447 m_confParam.getValidator(), options);
449 auto it = m_fetchers.insert(fetcher).first;
451 fetcher->afterSegmentValidated.connect([
this] (
const ndn::Data& data) {
453 afterSegmentValidatedSignal(data);
456 auto lsaSegment = std::make_shared<const ndn::Data>(data);
457 m_lsaStorage.insert(*lsaSegment);
460 [
this, name = lsaSegment->getName()] { m_lsaStorage.erase(name); });
463 fetcher->onComplete.connect([=] (
const ndn::ConstBufferPtr& bufferPtr) {
464 m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
465 afterFetchLsa(bufferPtr, interestName);
466 m_fetchers.erase(it);
469 fetcher->onError.connect([=] (uint32_t errorCode,
const std::string& msg) {
470 onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
471 m_fetchers.erase(it);
475 std::istringstream(interestName[-2].toUri()) >> lsaType;
476 incrementInterestSentStats(lsaType);
480 Lsdb::onFetchLsaError(uint32_t errorCode,
const std::string& msg,
const ndn::Name& interestName,
481 uint32_t retransmitNo,
const ndn::time::steady_clock::time_point& deadline,
482 ndn::Name lsaName, uint64_t seqNo)
484 NLSR_LOG_DEBUG(
"Failed to fetch LSA: " << lsaName <<
", Error code: " << errorCode
485 <<
", Message: " << msg);
487 if (ndn::time::steady_clock::now() < deadline) {
488 auto it = m_highestSeqNo.find(lsaName);
489 if (it != m_highestSeqNo.end() && it->second == seqNo) {
494 ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
496 if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
497 delay = ndn::time::seconds(0);
499 m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest,
this,
500 interestName, retransmitNo + 1, 0, deadline));
506 Lsdb::afterFetchLsa(
const ndn::ConstBufferPtr& bufferPtr,
const ndn::Name& interestName)
508 NLSR_LOG_DEBUG(
"Received data for LSA interest: " << interestName);
509 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
511 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
512 uint64_t seqNo = interestName[-1].toNumber();
514 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
515 m_highestSeqNo[lsaName] = seqNo;
517 else if (seqNo > m_highestSeqNo[lsaName]) {
518 m_highestSeqNo[lsaName] = seqNo;
519 NLSR_LOG_TRACE(
"SeqNo for LSA(name): " << interestName <<
" updated");
521 else if (seqNo < m_highestSeqNo[lsaName]) {
525 std::string chkString(
"LSA");
528 if (lsaPosition >= 0) {
530 ndn::Name originRouter = m_confParam.getNetwork();
531 originRouter.append(interestName.getSubName(lsaPosition + 1,
532 interestName.size() - lsaPosition - 3));
534 Lsa::Type interestedLsType;
535 std::istringstream(interestName[-2].toUri()) >> interestedLsType;
537 if (interestedLsType == Lsa::Type::BASE) {
538 NLSR_LOG_WARN(
"Received unrecognized LSA Type: " << interestName[-2].toUri());
542 ndn::Block block(bufferPtr);
543 if (interestedLsType == Lsa::Type::NAME) {
544 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
545 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
546 installLsa(std::make_shared<NameLsa>(block));
549 else if (interestedLsType == Lsa::Type::ADJACENCY) {
550 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
551 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
552 installLsa(std::make_shared<AdjLsa>(block));
555 else if (interestedLsType == Lsa::Type::COORDINATE) {
556 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
557 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
558 installLsa(std::make_shared<CoordinateLsa>(block));
562 catch (
const std::exception& e) {
A class to house all the configuration parameters for NLSR.
Data abstraction for CoordinateLsa CoordinateLsa := COORDINATE-LSA-TYPE TLV-LENGTH Lsa HyperbolicRadi...
Data abstraction for Lsa Lsa := LSA-TYPE TLV-LENGTH Name SequenceNumber ExpirationTimePoint.
Lsdb(ndn::Face &face, ndn::KeyChain &keyChain, ConfParameter &confParam)
Data abstraction for NameLsa NameLsa := NAME-LSA-TYPE TLV-LENGTH Lsa Name+.
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