diff --git a/.jenkins.d/02-chronosync.sh b/.jenkins.d/02-chronosync.sh index b798776..c93f3b9 100755 --- a/.jenkins.d/02-chronosync.sh +++ b/.jenkins.d/02-chronosync.sh @@ -9,15 +9,6 @@ set -x pushd "${CACHE_DIR:-/tmp}" >/dev/null INSTALLED_VERSION= -if has OSX $NODE_LABELS; then - BOOST=$(brew ls --versions boost) - OLD_BOOST=$(cat boost_chrono.txt || :) - if [[ $OLD_BOOST != $BOOST ]]; then - echo "$BOOST" > boost_chrono.txt - INSTALLED_VERSION=NONE - fi -fi - NDN_CXX=$(ndnsec version) OLD_NDN_CXX=$(cat ndn_cxx_chrono.txt || :) if [[ $OLD_NDN_CXX != $NDN_CXX ]]; then diff --git a/.jenkins.d/03-psync.sh b/.jenkins.d/03-psync.sh new file mode 100755 index 0000000..534115d --- /dev/null +++ b/.jenkins.d/03-psync.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -e + +JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +source "$JDIR"/util.sh + +set -x + +pushd "${CACHE_DIR:-/tmp}" >/dev/null + +INSTALLED_VERSION= +NDN_CXX=$(ndnsec version) +OLD_NDN_CXX=$(cat ndn_cxx_psync.txt || :) +if [[ $OLD_NDN_CXX != $NDN_CXX ]]; then + echo "$NDN_CXX" > ndn_cxx_psync.txt + INSTALLED_VERSION=NONE +fi + +if [[ -z $INSTALLED_VERSION ]]; then + INSTALLED_VERSION=$(git -C PSync rev-parse HEAD 2>/dev/null || echo NONE) +fi + +sudo rm -Rf PSync-latest + +git clone --depth 1 git://github.com/named-data/PSync PSync-latest + +LATEST_VERSION=$(git -C PSync-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN) + +if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then + sudo rm -Rf PSync + mv PSync-latest PSync +else + sudo rm -Rf PSync-latest +fi + +sudo rm -fr /usr/local/include/PSync +sudo rm -f /usr/local/lib/libPSync* +sudo rm -f /usr/local/lib/pkgconfig/PSync* + +pushd PSync >/dev/null + +if has FreeBSD10 $NODE_LABELS; then + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ +fi + +./waf configure --color=yes +./waf build --color=yes -j${WAF_JOBS:-1} +sudo env "PATH=$PATH" ./waf install --color=yes + +popd >/dev/null +popd >/dev/null + +if has Linux $NODE_LABELS; then + sudo ldconfig +elif has FreeBSD10 $NODE_LABELS; then + sudo ldconfig -m +fi diff --git a/COPYING.md b/COPYING.md index b5f29be..460ed34 100644 --- a/COPYING.md +++ b/COPYING.md @@ -15,6 +15,9 @@ licenses: - ChronoSync is licensed under the conditions of [GPL 3.0](https://github.com/named-data/ChronoSync/blob/master/COPYING.md) +- PSync is licensed under the conditions of + [LGPL 3.0](https://github.com/named-data/PSync/blob/master/COPYING.md) + - waf build system is licensed under the conditions of [BSD license](https://github.com/named-data/NLSR/blob/master/waf) diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst index d567598..da66e87 100644 --- a/docs/INSTALL.rst +++ b/docs/INSTALL.rst @@ -21,6 +21,15 @@ address: https://github.com/named-data/ChronoSync#build +- PSync library: + +Download the PSync library and build it according to the instructions at the following +address: + + :: + + https://github.com/named-data/PSync#build + Build ----- diff --git a/docs/beginners-guide.rst b/docs/beginners-guide.rst index ddbf4e6..9807191 100644 --- a/docs/beginners-guide.rst +++ b/docs/beginners-guide.rst @@ -18,7 +18,7 @@ A beginners guide to installing and testing NLSR on Fedora The following instructions are based on the information provided at the Named Data Networking project web page [NDNmain]_. Before installing NLSR it is necessary to install different libraries -and programs: ndn-cxx, NFD and ChronoSync. This document describes the +and programs: ndn-cxx, NFD, ChronoSync, and PSync. This document describes the necessary steps to correctly install these programs (§ `2 <#ndncxx>`__, `3 <#nfd>`__ and `4 <#nlsr>`__) and a brief guide on how to configure and test NLSR using a simple two-node network (§ `5 <#test>`__). @@ -365,9 +365,9 @@ commands: ------------------------- Before installing NLSR, it is necessary to first download and install -ChronoSync, which is a library that allows NLSR routers to verify that -their routing information coincides. More information about ChronoSync -may be found at [Chronosync]_. This library may be +ChronoSync, which is a synchronization library which allows NLSR routers +to synchronize Link State Advertisements (LSAs). More information about +ChronoSync may be found at [Chronosync]_. This library may be installed by running the following commands as a regular user and at the directory defined at § `1 <#intro>`__: @@ -383,7 +383,7 @@ The following command needs to be used again to configure the libraries: :: - $ sudo ldconfig -v | grep ndn + $ sudo ldconfig -v | grep -i chronosync This command should display a line similar to the following: @@ -391,7 +391,36 @@ This command should display a line similar to the following: libChronoSync.so.0.5.0 -> libChronoSync.so.0.5.0 -4.2 Downloading and installing NLSR +4.2 Installing PSync +------------------------- + +Before installing NLSR, it is also necessary to download and install +PSync. PSync is a synchronization library which allows NLSR to synchronize LSAs +similar to ChronoSync. More information about PSync may be found at [PSync]_. +This library may be installed by running the following commands as a regular +user and at the directory defined at § `1 <#intro>`__: + +:: + + $ git clone --depth 1 https://github.com/named-data/PSync.git + $ cd PSync + $ ./waf configure + $ ./waf + $ sudo ./waf install + +The following command needs to be used again to configure the libraries: + +:: + + $ sudo ldconfig -v | grep -i psync + +This command should display a line similar to the following: + +:: + + libPSync.so.0.1.0 -> libPSync.so.0.1.0 + +4.3 Downloading and installing NLSR ----------------------------------- NLSR is downloaded and installed in a folder called *NLSR* which should @@ -406,7 +435,7 @@ commands need to be run as a regular user: $ ./waf $ sudo ./waf install -4.3 Configuring NLSR +4.4 Configuring NLSR -------------------- Create and configure the following directory by running the following @@ -844,6 +873,8 @@ deployment [NDNTestbed]_. .. [Chronosync] Z. Zhu and A. Afanasyev. *Let’s ChronoSync: Decentralized dataset state synchronization in Named Data Networking*, in IEEE ICNP, October 2013. +.. [PSync] M. Zhang, V. Lehman, and L. Wang. *Scalable Name-based Data Synchronization for Named Data Networking*, in IEEE INFOCOM, May 2017. + .. [NLSRsecconf] *NLSR Security Configuration*, http://named-data.net/doc/NLSR/current/SECURITY-CONFIG.html June 2018. .. [NLSRdevguide] V. Lehman, M. Chowdhury, N. Gordon, A. Gawande. *NLSR Developer’s Guide*, University of Memphis, November 2017. diff --git a/nlsr.conf b/nlsr.conf index beed576..8e574f5 100644 --- a/nlsr.conf +++ b/nlsr.conf @@ -19,7 +19,10 @@ general ; InterestLifetime (in seconds) for LSA fetching lsa-interest-lifetime 4 ; default value 4. Valid values 1-60 - ; sync interest lifetime of ChronoSync in milliseconds + ; select sync protocol: chronosync or psync + sync-protocol psync + + ; sync interest lifetime of ChronoSync/PSync in milliseconds sync-interest-lifetime 60000 ; default value 60000. Valid values 1000-120,000 seq-dir /var/lib/nlsr ; path for sequence directory (Absolute path) diff --git a/src/communication/sync-logic-handler.cpp b/src/communication/sync-logic-handler.cpp index 1e8f90b..13f2e8e 100644 --- a/src/communication/sync-logic-handler.cpp +++ b/src/communication/sync-logic-handler.cpp @@ -23,16 +23,16 @@ #include "common.hpp" #include "conf-parameter.hpp" #include "lsa.hpp" -#include "utility/name-helper.hpp" #include "logger.hpp" +#include "utility/name-helper.hpp" namespace nlsr { -INIT_LOGGER(SyncLogicHandler); - const std::string NLSR_COMPONENT = "nlsr"; const std::string LSA_COMPONENT = "LSA"; +INIT_LOGGER(SyncLogicHandler); + template class NullDeleter { @@ -60,73 +60,59 @@ SyncLogicHandler::createSyncLogic(const ndn::Name& syncPrefix, const ndn::time:: return; } - m_syncPrefix = syncPrefix; - // Build LSA sync update prefix buildUpdatePrefix(); - NLSR_LOG_DEBUG("Creating Sync Logic object. Sync Prefix: " << m_syncPrefix); + NLSR_LOG_DEBUG("Creating Sync Logic object. Sync Prefix: " << syncPrefix); // The face's lifetime is managed in main.cpp; Logic should not manage the memory // of the object std::shared_ptr facePtr(&m_syncFace, NullDeleter()); - const auto fixedSession = ndn::name::Component::fromNumber(0); - m_syncLogic = std::make_shared(*facePtr, m_syncPrefix, m_nameLsaUserPrefix, - std::bind(&SyncLogicHandler::onChronoSyncUpdate, this, _1), - chronosync::Logic::DEFAULT_NAME, - chronosync::Logic::DEFAULT_VALIDATOR, - chronosync::Logic::DEFAULT_RESET_TIMER, - chronosync::Logic::DEFAULT_CANCEL_RESET_TIMER, - chronosync::Logic::DEFAULT_RESET_INTEREST_LIFETIME, - syncInterestLifetime, - chronosync::Logic::DEFAULT_SYNC_REPLY_FRESHNESS, - chronosync::Logic::DEFAULT_RECOVERY_INTEREST_LIFETIME, - fixedSession); + m_syncLogic = std::make_shared(*facePtr, + m_confParam.getSyncProtocol(), + syncPrefix, + m_nameLsaUserPrefix, + syncInterestLifetime, + std::bind(&SyncLogicHandler::processUpdate, this, _1, _2)); if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) { - m_syncLogic->addUserNode(m_adjLsaUserPrefix, chronosync::Logic::DEFAULT_NAME, fixedSession); + m_syncLogic->addUserNode(m_adjLsaUserPrefix); } else if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) { - m_syncLogic->addUserNode(m_coorLsaUserPrefix, chronosync::Logic::DEFAULT_NAME, fixedSession); + m_syncLogic->addUserNode(m_coorLsaUserPrefix); } else { - m_syncLogic->addUserNode(m_adjLsaUserPrefix, chronosync::Logic::DEFAULT_NAME, fixedSession); - m_syncLogic->addUserNode(m_coorLsaUserPrefix, chronosync::Logic::DEFAULT_NAME, fixedSession); + m_syncLogic->addUserNode(m_adjLsaUserPrefix); + m_syncLogic->addUserNode(m_coorLsaUserPrefix); } } void -SyncLogicHandler::onChronoSyncUpdate(const std::vector& v) +SyncLogicHandler::processUpdate(const ndn::Name& updateName, uint64_t highSeq) { - NLSR_LOG_DEBUG("Received ChronoSync update event"); + NLSR_LOG_DEBUG("Update Name: " << updateName << " Seq no: " << highSeq); - for (size_t i = 0; i < v.size(); i++){ - ndn::Name updateName = v[i].session.getPrefix(-1); + int32_t nlsrPosition = util::getNameComponentPosition(updateName, nlsr::NLSR_COMPONENT); + int32_t lsaPosition = util::getNameComponentPosition(updateName, nlsr::LSA_COMPONENT); - NLSR_LOG_DEBUG("Update Name: " << updateName << " Seq no: " << v[i].high); - - int32_t nlsrPosition = util::getNameComponentPosition(updateName, nlsr::NLSR_COMPONENT); - int32_t lsaPosition = util::getNameComponentPosition(updateName, nlsr::LSA_COMPONENT); - - if (nlsrPosition < 0 || lsaPosition < 0) { - NLSR_LOG_WARN("Received malformed sync update"); - return; - } - - ndn::Name networkName = updateName.getSubName(1, nlsrPosition-1); - ndn::Name routerName = updateName.getSubName(lsaPosition + 1).getPrefix(-1); - - ndn::Name originRouter = networkName; - originRouter.append(routerName); - - processUpdateFromSync(originRouter, updateName, v[i].high); + if (nlsrPosition < 0 || lsaPosition < 0) { + NLSR_LOG_WARN("Received malformed sync update"); + return; } + + ndn::Name networkName = updateName.getSubName(1, nlsrPosition-1); + ndn::Name routerName = updateName.getSubName(lsaPosition + 1).getPrefix(-1); + + ndn::Name originRouter = networkName; + originRouter.append(routerName); + + processUpdateFromSync(originRouter, updateName, highSeq); } void SyncLogicHandler::processUpdateFromSync(const ndn::Name& originRouter, - const ndn::Name& updateName, const uint64_t& seqNo) + const ndn::Name& updateName, uint64_t seqNo) { NLSR_LOG_DEBUG("Origin Router of update: " << originRouter); @@ -169,13 +155,13 @@ SyncLogicHandler::publishRoutingUpdate(const Lsa::Type& type, const uint64_t& se switch (type) { case Lsa::Type::ADJACENCY: - m_syncLogic->updateSeqNo(seqNo, m_adjLsaUserPrefix); + m_syncLogic->publishUpdate(m_adjLsaUserPrefix, seqNo); break; case Lsa::Type::COORDINATE: - m_syncLogic->updateSeqNo(seqNo, m_coorLsaUserPrefix); + m_syncLogic->publishUpdate(m_coorLsaUserPrefix, seqNo); break; case Lsa::Type::NAME: - m_syncLogic->updateSeqNo(seqNo, m_nameLsaUserPrefix); + m_syncLogic->publishUpdate(m_nameLsaUserPrefix, seqNo); break; default: break; diff --git a/src/communication/sync-logic-handler.hpp b/src/communication/sync-logic-handler.hpp index 8be327c..ae72fb8 100644 --- a/src/communication/sync-logic-handler.hpp +++ b/src/communication/sync-logic-handler.hpp @@ -26,10 +26,10 @@ #include "test-access-control.hpp" #include "signals.hpp" #include "lsa.hpp" +#include "sync-protocol-adapter.hpp" #include #include -#include #include class InterestManager; @@ -64,17 +64,6 @@ public: SyncLogicHandler(ndn::Face& face, const IsLsaNew& isLsaNew, const ConfParameter& conf); - /*! \brief Hook function to call whenever sync detects new data. - * - * This function packages the sync information into discrete updates - * and passes those off to another function, processUpdateFromSync. - * \sa processUpdateFromSync - * - * \param v A container with the new information sync has received - */ - void - onChronoSyncUpdate(const std::vector& v); - /*! \brief Instruct ChronoSync to publish an update. * * This function instructs sync to push an update into the network, @@ -99,13 +88,15 @@ public: const ndn::time::milliseconds& syncInterestLifetime = ndn::time::milliseconds(SYNC_INTEREST_LIFETIME_DEFAULT)); + void + processUpdate(const ndn::Name& updateName, uint64_t highSeq); + PUBLIC_WITH_TESTS_ELSE_PRIVATE: /*! \brief Simple function to glue Name components together */ void buildUpdatePrefix(); -private: /*! \brief Determine which kind of LSA was updated and fetch it. * * Checks that the received update is not from us, which can happen, @@ -116,15 +107,16 @@ private: */ void processUpdateFromSync(const ndn::Name& originRouter, - const ndn::Name& updateName, const uint64_t& seqNo); + const ndn::Name& updateName, uint64_t seqNo); public: std::unique_ptr onNewLsa; private: ndn::Face& m_syncFace; - std::shared_ptr m_syncLogic; - ndn::Name m_syncPrefix; +PUBLIC_WITH_TESTS_ELSE_PRIVATE: + std::shared_ptr m_syncLogic; +private: IsLsaNew m_isLsaNew; const ConfParameter& m_confParam; @@ -136,7 +128,6 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: private: static const std::string NLSR_COMPONENT; static const std::string LSA_COMPONENT; - }; } // namespace nlsr diff --git a/src/communication/sync-protocol-adapter.cpp b/src/communication/sync-protocol-adapter.cpp new file mode 100644 index 0000000..af263c8 --- /dev/null +++ b/src/communication/sync-protocol-adapter.cpp @@ -0,0 +1,110 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/** + * Copyright (c) 2014-2018, The University of Memphis, + * Regents of the University of California, + * Arizona Board of Regents. + * + * This file is part of NLSR (Named-data Link State Routing). + * See AUTHORS.md for complete list of NLSR authors and contributors. + * + * NLSR is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * NLSR, e.g., in COPYING.md file. If not, see . + **/ + +#include "sync-protocol-adapter.hpp" +#include "logger.hpp" + +INIT_LOGGER(SyncProtocolAdapter); + +namespace nlsr { + +const auto FIXED_SESSION = ndn::name::Component::fromNumber(0); + +SyncProtocolAdapter::SyncProtocolAdapter(ndn::Face& face, + int32_t syncProtocol, + const ndn::Name& syncPrefix, + const ndn::Name& userPrefix, + ndn::time::milliseconds syncInterestLifetime, + const SyncUpdateCallback& syncUpdateCallback) + : m_syncProtocol(syncProtocol) + , m_syncUpdateCallback(syncUpdateCallback) +{ + if (m_syncProtocol == SYNC_PROTOCOL_CHRONOSYNC) { + NDN_LOG_DEBUG("Using ChronoSync"); + m_chronoSyncLogic = std::make_shared(face, + syncPrefix, + userPrefix, + std::bind(&SyncProtocolAdapter::onChronoSyncUpdate, this, _1), + chronosync::Logic::DEFAULT_NAME, + chronosync::Logic::DEFAULT_VALIDATOR, + chronosync::Logic::DEFAULT_RESET_TIMER, + chronosync::Logic::DEFAULT_CANCEL_RESET_TIMER, + chronosync::Logic::DEFAULT_RESET_INTEREST_LIFETIME, + syncInterestLifetime, + chronosync::Logic::DEFAULT_SYNC_REPLY_FRESHNESS, + chronosync::Logic::DEFAULT_RECOVERY_INTEREST_LIFETIME, + FIXED_SESSION); + } + else { + NDN_LOG_DEBUG("Using PSync"); + m_psyncLogic = std::make_shared(80, + face, + syncPrefix, + userPrefix, + std::bind(&SyncProtocolAdapter::onPSyncUpdate, this, _1), + syncInterestLifetime); + } +} + +void +SyncProtocolAdapter::addUserNode(const ndn::Name& userPrefix) +{ + if (m_syncProtocol == SYNC_PROTOCOL_CHRONOSYNC) { + m_chronoSyncLogic->addUserNode(userPrefix, chronosync::Logic::DEFAULT_NAME, FIXED_SESSION); + } + else { + m_psyncLogic->addUserNode(userPrefix); + } +} + +void +SyncProtocolAdapter::publishUpdate(const ndn::Name& userPrefix, uint64_t seq) +{ + if (m_syncProtocol == SYNC_PROTOCOL_CHRONOSYNC) { + m_chronoSyncLogic->updateSeqNo(seq, userPrefix); + } + else { + m_psyncLogic->publishName(userPrefix, seq); + } +} + +void +SyncProtocolAdapter::onChronoSyncUpdate(const std::vector& updates) +{ + NLSR_LOG_TRACE("Received ChronoSync update event"); + + for (const auto& update : updates) { + // Remove FIXED_SESSION + m_syncUpdateCallback(update.session.getPrefix(-1), update.high); + } +} + +void +SyncProtocolAdapter::onPSyncUpdate(const std::vector& updates) +{ + NLSR_LOG_TRACE("Received PSync update event"); + + for (const auto& update : updates) { + m_syncUpdateCallback(update.prefix, update.highSeq); + } +} + +} // namespace nlsr \ No newline at end of file diff --git a/src/communication/sync-protocol-adapter.hpp b/src/communication/sync-protocol-adapter.hpp new file mode 100644 index 0000000..363f02d --- /dev/null +++ b/src/communication/sync-protocol-adapter.hpp @@ -0,0 +1,96 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/** + * Copyright (c) 2014-2018, The University of Memphis, + * Regents of the University of California, + * Arizona Board of Regents. + * + * This file is part of NLSR (Named-data Link State Routing). + * See AUTHORS.md for complete list of NLSR authors and contributors. + * + * NLSR is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * NLSR, e.g., in COPYING.md file. If not, see . + **/ + +#ifndef NLSR_SYNC_PROTOCOL_ADAPTER_HPP +#define NLSR_SYNC_PROTOCOL_ADAPTER_HPP + +#include "conf-parameter.hpp" + +#include +#include +#include + +namespace nlsr { + +typedef std::function SyncUpdateCallback; + +class SyncProtocolAdapter +{ +public: + SyncProtocolAdapter(ndn::Face& facePtr, + int32_t syncProtocol, + const ndn::Name& syncPrefix, + const ndn::Name& userPrefix, + ndn::time::milliseconds syncInterestLifetime, + const SyncUpdateCallback& syncUpdateCallback); + + /*! \brief Add user node to ChronoSync or PSync + * + * \param userPrefix the Name under which the application will publishData + */ + void + addUserNode(const ndn::Name& userPrefix); + + /*! \brief Publish update to ChronoSync or PSync + * + * NLSR forces sequences number on the sync protocol + * as it manages is its own sequence number by storing it in a file. + * + * \param userPrefix the Name to be updated + * \param seq the sequence of userPrefix + */ + void + publishUpdate(const ndn::Name& userPrefix, uint64_t seq); + +PUBLIC_WITH_TESTS_ELSE_PRIVATE: + /*! \brief Hook function to call whenever ChronoSync detects new data. + * + * This function packages the sync information into discrete updates + * and passes those off to another function, m_syncUpdateCallback. + * \sa m_syncUpdateCallback + * + * \param v A container with the new information sync has received + */ + void + onChronoSyncUpdate(const std::vector& updates); + + /*! \brief Hook function to call whenever PSync detects new data. + * + * This function packages the sync information into discrete updates + * and passes those off to another function, m_syncUpdateCallback. + * \sa m_syncUpdateCallback + * + * \param v A container with the new information sync has received + */ + void + onPSyncUpdate(const std::vector& updates); + +private: + int32_t m_syncProtocol; + SyncUpdateCallback m_syncUpdateCallback; + std::shared_ptr m_chronoSyncLogic; + std::shared_ptr m_psyncLogic; +}; + +} // namespace nlsr + +#endif // NLSR_SYNC_PROTOCOL_ADAPTER_HPP diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp index d388221..c893e39 100644 --- a/src/conf-file-processor.cpp +++ b/src/conf-file-processor.cpp @@ -287,6 +287,21 @@ ConfFileProcessor::processConfSectionGeneral(const ConfigSection& section) return false; } + // sync-protocol + std::string syncProtocol = section.get("sync-protocol", "chronosync"); + if (syncProtocol == "chronosync") { + m_nlsr.getConfParameter().setSyncProtocol(SYNC_PROTOCOL_CHRONOSYNC); + } + else if (syncProtocol == "psync") { + m_nlsr.getConfParameter().setSyncProtocol(SYNC_PROTOCOL_PSYNC); + } + else { + std::cerr << "Sync protocol " << syncProtocol << " is not supported!" + << "Use chronosync or psync" << std::endl; + return false; + } + + // sync-interest-lifetime uint32_t syncInterestLifetime = section.get("sync-interest-lifetime", SYNC_INTEREST_LIFETIME_DEFAULT); if (syncInterestLifetime >= SYNC_INTEREST_LIFETIME_MIN && syncInterestLifetime <= SYNC_INTEREST_LIFETIME_MAX) { diff --git a/src/conf-parameter.cpp b/src/conf-parameter.cpp index bb61456..eaaf76e 100644 --- a/src/conf-parameter.cpp +++ b/src/conf-parameter.cpp @@ -29,7 +29,7 @@ namespace nlsr { INIT_LOGGER(ConfParameter); // To be changed when breaking changes are made to sync -const uint64_t ConfParameter::SYNC_VERSION = 5; +const uint64_t ConfParameter::SYNC_VERSION = 6; void ConfParameter::writeLog() diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp index 8c0e1a9..df90cda 100644 --- a/src/conf-parameter.hpp +++ b/src/conf-parameter.hpp @@ -39,6 +39,11 @@ enum { LSA_REFRESH_TIME_MAX = 7200 }; +enum { + SYNC_PROTOCOL_CHRONOSYNC = 0, + SYNC_PROTOCOL_PSYNC = 1 +}; + enum { LSA_INTEREST_LIFETIME_MIN = 1, LSA_INTEREST_LIFETIME_DEFAULT = 4, @@ -136,7 +141,6 @@ public: , m_faceDatasetFetchInterval(ndn::time::seconds(static_cast(FACE_DATASET_FETCH_INTERVAL_DEFAULT))) , m_lsaInterestLifetime(ndn::time::seconds(static_cast(LSA_INTEREST_LIFETIME_DEFAULT))) , m_routerDeadInterval(2 * LSA_REFRESH_TIME_DEFAULT) - , m_logLevel("INFO") , m_interestRetryNumber(HELLO_RETRIES_DEFAULT) , m_interestResendTime(HELLO_TIMEOUT_DEFAULT) , m_infoInterestInterval(HELLO_INTERVAL_DEFAULT) @@ -144,6 +148,7 @@ public: , m_corR(0) , m_maxFacesPerPrefix(MAX_FACES_PER_PREFIX_MIN) , m_syncInterestLifetime(ndn::time::milliseconds(SYNC_INTEREST_LIFETIME_DEFAULT)) + , m_syncProtocol(SYNC_PROTOCOL_CHRONOSYNC) { } @@ -213,6 +218,20 @@ public: m_lsaRefreshTime = lrt; } + uint32_t + getSyncProtocol() const + { + return m_syncProtocol; + } + + void + setSyncProtocol(int32_t syncProtocol) + { + if (syncProtocol == SYNC_PROTOCOL_CHRONOSYNC || syncProtocol == SYNC_PROTOCOL_PSYNC) { + m_syncProtocol = syncProtocol; + } + } + uint32_t getLsaRefreshTime() const { @@ -440,7 +459,6 @@ private: ndn::time::seconds m_lsaInterestLifetime; uint32_t m_routerDeadInterval; - std::string m_logLevel; uint32_t m_interestRetryNumber; uint32_t m_interestResendTime; @@ -456,6 +474,8 @@ private: std::string m_seqFileDir; ndn::time::milliseconds m_syncInterestLifetime; + int32_t m_syncProtocol; + PUBLIC_WITH_TESTS_ELSE_PRIVATE: static const uint64_t SYNC_VERSION; }; diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp index 14fce9a..99ef78f 100644 --- a/tests/test-conf-file-processor.cpp +++ b/tests/test-conf-file-processor.cpp @@ -44,6 +44,7 @@ const std::string SECTION_GENERAL = " lsa-refresh-time 1800\n" " lsa-interest-lifetime 3\n" " router-dead-interval 86400\n" + " sync-protocol psync\n" " sync-interest-lifetime 10000\n" " seq-dir /tmp\n" "}\n\n"; @@ -175,6 +176,7 @@ BOOST_AUTO_TEST_CASE(LinkState) BOOST_CHECK_EQUAL(conf.getChronosyncPrefix(), ndn::Name("/localhop/ndn/nlsr/sync").appendVersion(ConfParameter::SYNC_VERSION)); BOOST_CHECK_EQUAL(conf.getLsaPrefix(), "/localhop/ndn/nlsr/LSA"); BOOST_CHECK_EQUAL(conf.getLsaRefreshTime(), 1800); + BOOST_CHECK_EQUAL(conf.getSyncProtocol(), SYNC_PROTOCOL_PSYNC); BOOST_CHECK_EQUAL(conf.getLsaInterestLifetime(), ndn::time::seconds(3)); BOOST_CHECK_EQUAL(conf.getRouterDeadInterval(), 86400); BOOST_CHECK_EQUAL(conf.getSyncInterestLifetime(), ndn::time::milliseconds(10000)); diff --git a/tests/test-conf-parameter.cpp b/tests/test-conf-parameter.cpp index 55a65b1..0fdf631 100644 --- a/tests/test-conf-parameter.cpp +++ b/tests/test-conf-parameter.cpp @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /** - * Copyright (c) 2014-2017, The University of Memphis, + * Copyright (c) 2014-2018, The University of Memphis, * Regents of the University of California * * This file is part of NLSR (Named-data Link State Routing). @@ -53,6 +53,8 @@ BOOST_AUTO_TEST_CASE(ConfParameterSettersAndGetters) cp1.setLsaInterestLifetime(ndn::time::seconds(1)); + cp1.setSyncProtocol(SYNC_PROTOCOL_PSYNC); + cp1.setRouterDeadInterval(10); cp1.setMaxFacesPerPrefix(50); @@ -85,6 +87,8 @@ BOOST_AUTO_TEST_CASE(ConfParameterSettersAndGetters) BOOST_CHECK_EQUAL(cp1.getLsaInterestLifetime(), ndn::time::seconds(1)); + BOOST_CHECK_EQUAL(cp1.getSyncProtocol(), SYNC_PROTOCOL_PSYNC); + BOOST_CHECK_EQUAL(cp1.getRouterDeadInterval(), 10); BOOST_CHECK_EQUAL(cp1.getMaxFacesPerPrefix(), 50); diff --git a/tests/test-sync-logic-handler.cpp b/tests/test-sync-logic-handler.cpp index ab9732d..021743c 100644 --- a/tests/test-sync-logic-handler.cpp +++ b/tests/test-sync-logic-handler.cpp @@ -60,18 +60,31 @@ public: addIdentity(conf.getRouterPrefix()); } + template + void + setSyncProtocol() + { + nlsr.getConfParameter().setSyncProtocol(N); + conf.setSyncProtocol(N); + } + + template void receiveUpdate(std::string prefix, uint64_t seqNo, SyncLogicHandler& p_sync) { - chronosync::MissingDataInfo info = {ndn::Name(prefix).appendNumber(1), 0, seqNo}; - - std::vector updates; - updates.push_back(info); - this->advanceClocks(ndn::time::milliseconds(1), 10); face.sentInterests.clear(); - p_sync.onChronoSyncUpdate(updates); + if (N == SYNC_PROTOCOL_CHRONOSYNC) { + std::vector updates; + updates.push_back({ndn::Name(prefix).appendNumber(1), 0, seqNo}); + p_sync.m_syncLogic->onChronoSyncUpdate(updates); + } + else { + std::vector updates; + updates.push_back({ndn::Name(prefix), 0, seqNo}); + p_sync.m_syncLogic->onPSyncUpdate(updates); + } this->advanceClocks(ndn::time::milliseconds(1), 10); } @@ -90,14 +103,19 @@ public: Lsa::Type::COORDINATE}; }; +using boost::mpl::int_; +using Protocols = boost::mpl::vector, int_>; + BOOST_FIXTURE_TEST_SUITE(TestSyncLogicHandler, SyncLogicFixture) /* Tests that when SyncLogicHandler receives an LSA of either Name or Adjacency type that appears to be newer, it will emit to its signal with those LSA details. */ -BOOST_AUTO_TEST_CASE(UpdateForOtherLS) +BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateForOtherLS, SyncProtocol, Protocols) { + setSyncProtocol(); + SyncLogicHandler sync{face, testIsLsaNew, conf}; sync.createSyncLogic(conf.getChronosyncPrefix()); @@ -116,7 +134,7 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherLS) BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo); }); - receiveUpdate(updateName, syncSeqNo, sync); + receiveUpdate(updateName, syncSeqNo, sync); } } @@ -124,8 +142,10 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherLS) either Coordinate or Name type that appears to be newer, it will emit to its signal with those LSA details. */ -BOOST_AUTO_TEST_CASE(UpdateForOtherHR) +BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateForOtherHR, SyncProtocol, Protocols) { + setSyncProtocol(); + conf.setHyperbolicState(HYPERBOLIC_STATE_ON); SyncLogicHandler sync{face, testIsLsaNew, conf}; @@ -144,7 +164,7 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherHR) BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo); }); - receiveUpdate(updateName, syncSeqNo, sync); + receiveUpdate(updateName, syncSeqNo, sync); } } @@ -152,8 +172,10 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherHR) any type that appears to be newer, it will emit to its signal with those LSA details. */ -BOOST_AUTO_TEST_CASE(UpdateForOtherHRDry) +BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateForOtherHRDry, SyncProtocol, Protocols) { + setSyncProtocol(); + conf.setHyperbolicState(HYPERBOLIC_STATE_DRY_RUN); SyncLogicHandler sync{face, testIsLsaNew, conf}; @@ -171,7 +193,7 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherHRDry) BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo); }); - receiveUpdate(updateName, syncSeqNo, sync); + receiveUpdate(updateName, syncSeqNo, sync); } } @@ -179,8 +201,10 @@ BOOST_AUTO_TEST_CASE(UpdateForOtherHRDry) details matching this router's details, it will *not* emit to its signal those LSA details. */ -BOOST_AUTO_TEST_CASE(NoUpdateForSelf) +BOOST_AUTO_TEST_CASE_TEMPLATE(NoUpdateForSelf, SyncProtocol, Protocols) { + setSyncProtocol(); + const uint64_t sequenceNumber = 1; SyncLogicHandler sync{face, testIsLsaNew, conf}; @@ -197,7 +221,7 @@ BOOST_AUTO_TEST_CASE(NoUpdateForSelf) BOOST_FAIL("Updates for self should not be emitted!"); }); - receiveUpdate(updateName.toUri(), sequenceNumber, sync); + receiveUpdate(updateName.toUri(), sequenceNumber, sync); } } @@ -205,8 +229,10 @@ BOOST_AUTO_TEST_CASE(NoUpdateForSelf) details that do not match the expected format, it will *not* emit to its signal those LSA details. */ -BOOST_AUTO_TEST_CASE(MalformedUpdate) +BOOST_AUTO_TEST_CASE_TEMPLATE(MalformedUpdate, SyncProtocol, Protocols) { + setSyncProtocol(); + const uint64_t sequenceNumber = 1; SyncLogicHandler sync{face, testIsLsaNew, conf}; @@ -221,7 +247,7 @@ BOOST_AUTO_TEST_CASE(MalformedUpdate) BOOST_FAIL("Malformed updates should not be emitted!"); }); - receiveUpdate(updateName.toUri(), sequenceNumber, sync); + receiveUpdate(updateName.toUri(), sequenceNumber, sync); } } @@ -229,8 +255,10 @@ BOOST_AUTO_TEST_CASE(MalformedUpdate) details that do not appear to be new, it will *not* emit to its signal those LSA details. */ -BOOST_AUTO_TEST_CASE(LsaNotNew) +BOOST_AUTO_TEST_CASE_TEMPLATE(LsaNotNew, SyncProtocol, Protocols) { + setSyncProtocol(); + auto testLsaAlwaysFalse = [] (const ndn::Name& routerName, const Lsa::Type& lsaType, const uint64_t& sequenceNumber) { return false; @@ -248,15 +276,16 @@ BOOST_AUTO_TEST_CASE(LsaNotNew) CONFIG_SITE + "/%C1.Router/other-router/" + std::to_string(Lsa::Type::NAME); - receiveUpdate(updateName, sequenceNumber, sync); + receiveUpdate(updateName, sequenceNumber, sync); } /* Tests that SyncLogicHandler successfully concatenates configured variables together to form the necessary prefixes to advertise through ChronoSync. */ -BOOST_AUTO_TEST_CASE(UpdatePrefix) +BOOST_AUTO_TEST_CASE_TEMPLATE(UpdatePrefix, SyncProtocol, Protocols) { + setSyncProtocol(); SyncLogicHandler sync{face, testIsLsaNew, conf}; @@ -281,8 +310,9 @@ BOOST_AUTO_TEST_CASE(UpdatePrefix) NB: This test is as much an Nlsr class test as a SyncLogicHandler class test, but it rides the line and ends up here. */ -BOOST_AUTO_TEST_CASE(createSyncLogicOnInitialization) // Bug #2649 +BOOST_AUTO_TEST_CASE_TEMPLATE(createSyncLogicOnInitialization, SyncProtocol, Protocols) // Bug #2649 { + setSyncProtocol(); nlsr.initialize(); // Make sure an adjacency LSA has not been built yet diff --git a/tests/test-sync-protocol-adapter.cpp b/tests/test-sync-protocol-adapter.cpp new file mode 100644 index 0000000..344f9a0 --- /dev/null +++ b/tests/test-sync-protocol-adapter.cpp @@ -0,0 +1,117 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/** + * Copyright (c) 2014-2018, The University of Memphis, + * Regents of the University of California, + * Arizona Board of Regents. + * + * This file is part of NLSR (Named-data Link State Routing). + * See AUTHORS.md for complete list of NLSR authors and contributors. + * + * NLSR is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * NLSR, e.g., in COPYING.md file. If not, see . + **/ + +#include "communication/sync-protocol-adapter.hpp" +#include "test-common.hpp" +#include "boost-test.hpp" + +#include + +#include +#include + +namespace nlsr { +namespace test { + +using namespace ndn; + +class SyncProtocolAdapterFixture : public UnitTestTimeFixture +{ +public: + SyncProtocolAdapterFixture() + : syncPrefix("/localhop/ndn/nlsr/sync/") + , nameLsaUserPrefix("/localhop/ndn/nlsr/LSA/NAME") + , syncInterestLifetime(time::seconds(60)) + { + syncPrefix.appendVersion(4); + } + + template + void + addNodes() + { + for (int i = 0; i < 2; i++) { + faces[i] = std::make_shared(m_ioService, + util::DummyClientFace::Options{true, true}); + userPrefixes[i] = Name(nameLsaUserPrefix).appendNumber(i); + nodes[i] = std::make_shared(*faces[i], T, syncPrefix, + userPrefixes[i], + syncInterestLifetime, + [i, this] (const ndn::Name& updateName, + uint64_t highSeq) { + prefixToSeq[i].emplace(updateName, highSeq); + }); + } + + faces[0]->linkTo(*faces[1]); + advanceClocks(ndn::time::milliseconds(10), 10); + } + +public: + Name syncPrefix, nameLsaUserPrefix; + Name userPrefixes[2]; + time::milliseconds syncInterestLifetime; + std::shared_ptr faces[2]; + std::shared_ptr nodes[2]; + std::map prefixToSeq[2]; +}; + +using boost::mpl::int_; +using Protocols = boost::mpl::vector, int_>; + +BOOST_FIXTURE_TEST_SUITE(TestSyncProtocolAdapter, SyncProtocolAdapterFixture) + +BOOST_AUTO_TEST_CASE_TEMPLATE(Sync, SyncProtocol, Protocols) +{ + addNodes(); + + nodes[0]->publishUpdate(userPrefixes[0], 10); + advanceClocks(ndn::time::milliseconds(1000), 100); + + auto it = prefixToSeq[1].find(userPrefixes[0]); + BOOST_CHECK(it != prefixToSeq[1].end()); + BOOST_CHECK_EQUAL(it->first, userPrefixes[0]); + BOOST_CHECK_EQUAL(it->second, 10); + + nodes[1]->publishUpdate(userPrefixes[1], 100); + advanceClocks(ndn::time::milliseconds(1000), 100); + + it = prefixToSeq[0].find(userPrefixes[1]); + BOOST_CHECK(it != prefixToSeq[0].end()); + BOOST_CHECK_EQUAL(it->first, userPrefixes[1]); + BOOST_CHECK_EQUAL(it->second, 100); + + Name adjLsaUserPrefix("/localhop/ndn/nlsr/LSA/ADJACENCY"); + nodes[0]->addUserNode(adjLsaUserPrefix); + advanceClocks(ndn::time::milliseconds(1000), 100); + nodes[0]->publishUpdate(adjLsaUserPrefix, 10); + advanceClocks(ndn::time::milliseconds(1000), 100); + + it = prefixToSeq[1].find(adjLsaUserPrefix); + BOOST_CHECK(it != prefixToSeq[1].end()); + BOOST_CHECK_EQUAL(it->first, adjLsaUserPrefix); + BOOST_CHECK_EQUAL(it->second, 10); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace test +} // namespace nlsr \ No newline at end of file diff --git a/wscript b/wscript index 5b9b8f8..82252a6 100644 --- a/wscript +++ b/wscript @@ -64,6 +64,9 @@ def configure(conf): conf.check_cfg(package='ChronoSync', args=['--cflags', '--libs'], uselib_store='SYNC', mandatory=True) + conf.check_cfg(package='PSync', args=['--cflags', '--libs'], + uselib_store='PSYNC', mandatory=True) + conf.check_compiler_flags() conf.load('coverage') @@ -96,7 +99,7 @@ def build(bld): target='nlsr-objects', source=bld.path.ant_glob(['src/**/*.cpp'], excl=['src/main.cpp']), - use='NDN_CXX BOOST SYNC', + use='NDN_CXX BOOST SYNC PSYNC', includes='. src', export_includes='. src')