Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2666473042 | ||
|
|
5b6deaea18 | ||
|
|
971d3c2b09 | ||
|
|
dbe4f9fefe | ||
|
|
692842d6ad | ||
|
|
cb6e05f2dd | ||
|
|
5620fb2ac9 | ||
|
|
965d3a4e72 | ||
|
|
187ade8566 |
No files matched your search
@@ -73,3 +73,7 @@ in the library:
|
||||
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Spyridon Mastorakis <http://cs.ucla.edu/~mastorakis/>
|
||||
* Eric Newberry <http://ericnewberry.com>
|
||||
* Yukai Tu <tuyukai1994@gmail.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* Mathias Gibbens <gibmat@cs.arizona.edu>
|
||||
@@ -0,0 +1,130 @@
|
||||
Starting NFD on Linux with systemd
|
||||
==================================
|
||||
|
||||
Newer versions of Ubuntu (starting with 15.04) and some other Linux distributions, including Debian
|
||||
use systemd to start system daemons, monitor their health, and restart them when they die.
|
||||
|
||||
Initial setup
|
||||
-------------
|
||||
|
||||
* Edit `nfd.service`, correcting the paths to the `nfd` executable, configuration, and
|
||||
``HOME`` directories.
|
||||
|
||||
* Copy the systemd config file for NFD to the proper directory
|
||||
|
||||
sudo cp nfd.service /etc/systemd/system
|
||||
|
||||
* Reload the systemd manager configuration
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
### Assumptions in the default scripts
|
||||
|
||||
* `nfd` is installed into `/usr/local/bin`
|
||||
* Configuraton file is `/usr/local/etc/ndn/nfd.conf`
|
||||
* `nfd` will be run as root
|
||||
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
|
||||
|
||||
### Creating users
|
||||
|
||||
If the `ndn` user and group do not exist, they need to be manually created.
|
||||
|
||||
# Create group `ndn`
|
||||
sudo addgroup --system ndn
|
||||
|
||||
# Create user `ndn`
|
||||
sudo adduser --system \
|
||||
--disabled-login \
|
||||
--ingroup ndn \
|
||||
--home /nonexistent \
|
||||
--gecos "NDN User" \
|
||||
--shell /bin/false \
|
||||
ndn
|
||||
|
||||
|
||||
### Creating folders
|
||||
|
||||
Folder `/usr/local/var/log/ndn` should be created and assigned proper user and group:
|
||||
|
||||
sudo mkdir -p /usr/local/var/log/ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/log/ndn
|
||||
|
||||
`HOME` directory for `nfd` should be created prior to starting. This is necessary to manage
|
||||
unique security credentials for the daemon.
|
||||
|
||||
# Create HOME and generate self-signed NDN certificate for nfd
|
||||
sudo sh -c ' \
|
||||
mkdir -p /usr/local/var/lib/ndn/nfd/.ndn; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
ndnsec-keygen /localhost/daemons/nfd | ndnsec-install-cert -; \
|
||||
'
|
||||
|
||||
### Configuring NFD's security
|
||||
|
||||
NFD sample configuration allows anybody to create faces, add nexthops to FIB, and set
|
||||
strategy choice for namespaces. While such settings could be a good start, it is
|
||||
generally not a good idea to run NFD in this mode.
|
||||
|
||||
While thorough discussion about the security configuration of NFD is outside the scope of
|
||||
this document, at least the following change should be done in ``nfd.conf`` in the
|
||||
authorize section:
|
||||
|
||||
authorizations
|
||||
{
|
||||
authorize
|
||||
{
|
||||
certfile certs/localhost_daemons_nfd.ndncert
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
fib
|
||||
strategy-choice
|
||||
}
|
||||
}
|
||||
|
||||
authorize
|
||||
{
|
||||
certfile any
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
strategy-choice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
While this configuration still allows the management of faces and updating strategy choice by
|
||||
anyone, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
|
||||
|
||||
As the final step to make this configuration work, nfd's self-signed certificate needs to
|
||||
be exported into the `localhost_daemons_nfd.ndncert` file:
|
||||
|
||||
sudo sh -c '\
|
||||
mkdir -p /usr/local/etc/ndn/certs || true; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
ndnsec-dump-certificate -i /localhost/daemons/nfd > \
|
||||
/usr/local/etc/ndn/certs/localhost_daemons_nfd.ndncert; \
|
||||
'
|
||||
|
||||
Enable auto-start
|
||||
-----------------
|
||||
|
||||
After copying the provided upstart script, auto-start of the `nfd` daemon can be enabled with:
|
||||
|
||||
sudo systemctl enable nfd
|
||||
|
||||
To manually start it, use the following command:
|
||||
|
||||
sudo systemctl start nfd
|
||||
|
||||
Disable auto-start
|
||||
------------------
|
||||
|
||||
To stop the `nfd` daemon, use the following command:
|
||||
|
||||
sudo systemctl stop nfd
|
||||
|
||||
To permanently stop the `nfd` daemon and disable it from being automatically started on reboot,
|
||||
disable the service:
|
||||
|
||||
sudo systemctl disable nfd
|
||||
@@ -0,0 +1,42 @@
|
||||
# Copyright (c) 2015, Regents of the University of California,
|
||||
# Arizona Board of Regents,
|
||||
# Colorado State University,
|
||||
# University Pierre & Marie Curie, Sorbonne University,
|
||||
# Washington University in St. Louis,
|
||||
# Beijing Institute of Technology,
|
||||
# The University of Memphis.
|
||||
#
|
||||
# This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
# See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
#
|
||||
# NFD 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.
|
||||
#
|
||||
# NFD 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
|
||||
# NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author: Eric Newberry <enewberry@email.arizona.edu>
|
||||
|
||||
[Unit]
|
||||
Description=NDN Forwarding Daemon
|
||||
Documentation=man:nfd man:nfdc man:nfd-status
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Environment=HOME=/usr/local/var/lib/ndn/nfd
|
||||
ExecStart=/usr/local/bin/nfd --config /usr/local/etc/ndn/nfd.conf
|
||||
ExecStartPost=/bin/sh -ec 'sleep 2; if [ -f /usr/local/etc/ndn/nfd-init.sh ]; then . /usr/local/etc/ndn/nfd-init.sh; fi'
|
||||
Restart=on-failure
|
||||
ProtectSystem=full
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectHome=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -97,8 +97,8 @@ AccessStrategy::afterReceiveNewInterest(const Face& inFace,
|
||||
|
||||
// no measurements, or last working nexthop unavailable
|
||||
|
||||
// multicast to all nexthops
|
||||
this->multicast(pitEntry, fibEntry);
|
||||
// multicast to all nexthops except incoming face
|
||||
this->multicast(pitEntry, fibEntry, {inFace.getId()});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -108,7 +108,7 @@ AccessStrategy::afterReceiveRetxInterest(const Face& inFace,
|
||||
shared_ptr<pit::Entry> pitEntry)
|
||||
{
|
||||
NFD_LOG_DEBUG(interest << " interestFrom " << inFace.getId() << " retx-forward");
|
||||
this->multicast(pitEntry, fibEntry, std::unordered_set<FaceId>{inFace.getId()});
|
||||
this->multicast(pitEntry, fibEntry, {inFace.getId()});
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -167,7 +167,7 @@ AccessStrategy::afterRtoTimeout(weak_ptr<pit::Entry> pitWeak, weak_ptr<fib::Entr
|
||||
|
||||
NFD_LOG_DEBUG(pitEntry->getInterest() << " timeoutFrom " << firstOutFace <<
|
||||
" multicast-except " << inFace << ',' << firstOutFace);
|
||||
this->multicast(pitEntry, fibEntry, std::unordered_set<FaceId>{inFace, firstOutFace});
|
||||
this->multicast(pitEntry, fibEntry, {inFace, firstOutFace});
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -35,7 +35,6 @@ EntryImpl::EntryImpl(const Name& name)
|
||||
}
|
||||
|
||||
EntryImpl::EntryImpl(shared_ptr<const Data> data, bool isUnsolicited)
|
||||
: queueType(QUEUE_NONE)
|
||||
{
|
||||
this->setData(data, isUnsolicited);
|
||||
BOOST_ASSERT(!this->isQuery());
|
||||
|
||||
@@ -26,9 +26,7 @@
|
||||
#ifndef NFD_DAEMON_TABLE_CS_ENTRY_IMPL_HPP
|
||||
#define NFD_DAEMON_TABLE_CS_ENTRY_IMPL_HPP
|
||||
|
||||
#include "cs-internal.hpp"
|
||||
#include "cs-entry.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
@@ -69,11 +67,6 @@ private:
|
||||
bool
|
||||
isQuery() const;
|
||||
|
||||
public:
|
||||
QueueType queueType;
|
||||
QueueIt queueIt;
|
||||
scheduler::EventId moveStaleEvent;
|
||||
|
||||
private:
|
||||
Name m_queryName;
|
||||
};
|
||||
|
||||
@@ -38,18 +38,7 @@ namespace cs {
|
||||
class EntryImpl;
|
||||
|
||||
typedef std::set<EntryImpl> Table;
|
||||
typedef Table::const_iterator TableIt;
|
||||
|
||||
typedef std::list<TableIt> Queue;
|
||||
typedef Queue::iterator QueueIt;
|
||||
|
||||
enum QueueType {
|
||||
QUEUE_UNSOLICITED,
|
||||
QUEUE_STALE,
|
||||
QUEUE_FIFO,
|
||||
QUEUE_MAX,
|
||||
QUEUE_NONE = QUEUE_MAX
|
||||
};
|
||||
typedef Table::const_iterator iterator;
|
||||
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cs-policy-priority-fifo.hpp"
|
||||
#include "cs.hpp"
|
||||
#include <ndn-cxx/util/signal.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
namespace priority_fifo {
|
||||
|
||||
const std::string PriorityFifoPolicy::POLICY_NAME = "fifo";
|
||||
|
||||
PriorityFifoPolicy::PriorityFifoPolicy()
|
||||
: Policy(POLICY_NAME)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::doAfterInsert(iterator i)
|
||||
{
|
||||
this->attachQueue(i);
|
||||
this->evictEntries();
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::doAfterRefresh(iterator i)
|
||||
{
|
||||
this->detachQueue(i);
|
||||
this->attachQueue(i);
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::doBeforeErase(iterator i)
|
||||
{
|
||||
this->detachQueue(i);
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::doBeforeUse(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_entryInfoMap.find(i) != m_entryInfoMap.end());
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::evictEntries()
|
||||
{
|
||||
BOOST_ASSERT(this->getCs() != nullptr);
|
||||
|
||||
while (this->getCs()->size() > this->getLimit()) {
|
||||
this->evictOne();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::evictOne()
|
||||
{
|
||||
BOOST_ASSERT(!m_queues[QUEUE_UNSOLICITED].empty() ||
|
||||
!m_queues[QUEUE_STALE].empty() ||
|
||||
!m_queues[QUEUE_FIFO].empty());
|
||||
|
||||
iterator i;
|
||||
if (!m_queues[QUEUE_UNSOLICITED].empty()) {
|
||||
i = m_queues[QUEUE_UNSOLICITED].front();
|
||||
}
|
||||
else if (!m_queues[QUEUE_STALE].empty()) {
|
||||
i = m_queues[QUEUE_STALE].front();
|
||||
}
|
||||
else if (!m_queues[QUEUE_FIFO].empty()) {
|
||||
i = m_queues[QUEUE_FIFO].front();
|
||||
}
|
||||
|
||||
this->detachQueue(i);
|
||||
this->emitSignal(beforeEvict, i);
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::attachQueue(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_entryInfoMap.find(i) == m_entryInfoMap.end());
|
||||
|
||||
EntryInfo* entryInfo = new EntryInfo();
|
||||
if (i->isUnsolicited()) {
|
||||
entryInfo->queueType = QUEUE_UNSOLICITED;
|
||||
}
|
||||
else if (i->isStale()) {
|
||||
entryInfo->queueType = QUEUE_STALE;
|
||||
}
|
||||
else {
|
||||
entryInfo->queueType = QUEUE_FIFO;
|
||||
|
||||
if (i->canStale()) {
|
||||
entryInfo->moveStaleEventId = scheduler::schedule(i->getData().getFreshnessPeriod(),
|
||||
bind(&PriorityFifoPolicy::moveToStaleQueue, this, i));
|
||||
}
|
||||
}
|
||||
|
||||
Queue& queue = m_queues[entryInfo->queueType];
|
||||
entryInfo->queueIt = queue.insert(queue.end(), i);
|
||||
m_entryInfoMap[i] = entryInfo;
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::detachQueue(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_entryInfoMap.find(i) != m_entryInfoMap.end());
|
||||
|
||||
EntryInfo* entryInfo = m_entryInfoMap[i];
|
||||
if (entryInfo->queueType == QUEUE_FIFO) {
|
||||
scheduler::cancel(entryInfo->moveStaleEventId);
|
||||
}
|
||||
|
||||
m_queues[entryInfo->queueType].erase(entryInfo->queueIt);
|
||||
m_entryInfoMap.erase(i);
|
||||
}
|
||||
|
||||
void
|
||||
PriorityFifoPolicy::moveToStaleQueue(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_entryInfoMap.find(i) != m_entryInfoMap.end());
|
||||
|
||||
EntryInfo* entryInfo = m_entryInfoMap[i];
|
||||
BOOST_ASSERT(entryInfo->queueType == QUEUE_FIFO);
|
||||
|
||||
m_queues[QUEUE_FIFO].erase(entryInfo->queueIt);
|
||||
|
||||
entryInfo->queueType = QUEUE_STALE;
|
||||
Queue& queue = m_queues[QUEUE_STALE];
|
||||
entryInfo->queueIt = queue.insert(queue.end(), i);
|
||||
m_entryInfoMap[i] = entryInfo;
|
||||
}
|
||||
|
||||
} // namespace priorityfifo
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,133 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
|
||||
#define NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
|
||||
|
||||
#include "cs-policy.hpp"
|
||||
#include "common.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
namespace priority_fifo {
|
||||
|
||||
typedef std::list<iterator> Queue;
|
||||
typedef Queue::iterator QueueIt;
|
||||
|
||||
enum QueueType {
|
||||
QUEUE_UNSOLICITED,
|
||||
QUEUE_STALE,
|
||||
QUEUE_FIFO,
|
||||
QUEUE_MAX
|
||||
};
|
||||
|
||||
struct EntryInfo
|
||||
{
|
||||
QueueType queueType;
|
||||
QueueIt queueIt;
|
||||
scheduler::EventId moveStaleEventId;
|
||||
};
|
||||
|
||||
struct EntryItComparator
|
||||
{
|
||||
bool
|
||||
operator()(const iterator& a, const iterator& b) const
|
||||
{
|
||||
return *a < *b;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<iterator, EntryInfo*, EntryItComparator> EntryInfoMapFifo;
|
||||
|
||||
/** \brief Priority Fifo cs replacement policy
|
||||
*
|
||||
* The entries that get removed first are unsolicited Data packets,
|
||||
* which are the Data packets that got cached opportunistically without preceding
|
||||
* forwarding of the corresponding Interest packet.
|
||||
* Next, the Data packets with expired freshness are removed.
|
||||
* Last, the Data packets are removed from the Content Store on a pure FIFO basis.
|
||||
*/
|
||||
class PriorityFifoPolicy : public Policy
|
||||
{
|
||||
public:
|
||||
PriorityFifoPolicy();
|
||||
|
||||
public:
|
||||
static const std::string POLICY_NAME;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
doAfterInsert(iterator i) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
doAfterRefresh(iterator i) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
doBeforeErase(iterator i) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
doBeforeUse(iterator i) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
evictEntries() DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
/** \brief evicts one entry
|
||||
* \pre CS is not empty
|
||||
*/
|
||||
void
|
||||
evictOne();
|
||||
|
||||
/** \brief attaches the entry to an appropriate queue
|
||||
* \pre the entry is not in any queue
|
||||
*/
|
||||
void
|
||||
attachQueue(iterator i);
|
||||
|
||||
/** \brief detaches the entry from its current queue
|
||||
* \post the entry is not in any queue
|
||||
*/
|
||||
void
|
||||
detachQueue(iterator i);
|
||||
|
||||
/** \brief moves an entry from FIFO queue to STALE queue
|
||||
*/
|
||||
void
|
||||
moveToStaleQueue(iterator i);
|
||||
|
||||
private:
|
||||
Queue m_queues[QUEUE_MAX];
|
||||
EntryInfoMapFifo m_entryInfoMap;
|
||||
};
|
||||
|
||||
} // namespace priorityfifo
|
||||
|
||||
using priority_fifo::PriorityFifoPolicy;
|
||||
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
|
||||
@@ -0,0 +1,79 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cs-policy.hpp"
|
||||
#include "cs.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
|
||||
Policy::Policy(const std::string& policyName)
|
||||
: m_policyName(policyName)
|
||||
{
|
||||
}
|
||||
|
||||
Policy::~Policy()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Policy::setLimit(size_t nMaxEntries)
|
||||
{
|
||||
BOOST_ASSERT(nMaxEntries > 0);
|
||||
m_limit = nMaxEntries;
|
||||
|
||||
this->evictEntries();
|
||||
}
|
||||
|
||||
void
|
||||
Policy::afterInsert(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_cs != nullptr);
|
||||
this->doAfterInsert(i);
|
||||
}
|
||||
|
||||
void
|
||||
Policy::afterRefresh(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_cs != nullptr);
|
||||
this->doAfterRefresh(i);
|
||||
}
|
||||
|
||||
void
|
||||
Policy::beforeErase(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_cs != nullptr);
|
||||
this->doBeforeErase(i);
|
||||
}
|
||||
|
||||
void
|
||||
Policy::beforeUse(iterator i)
|
||||
{
|
||||
BOOST_ASSERT(m_cs != nullptr);
|
||||
this->doBeforeUse(i);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,191 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_TABLE_CS_POLICY_HPP
|
||||
#define NFD_DAEMON_TABLE_CS_POLICY_HPP
|
||||
|
||||
#include "cs-internal.hpp"
|
||||
#include "cs-entry-impl.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
|
||||
class Cs;
|
||||
|
||||
/** \brief represents a CS replacement policy
|
||||
*/
|
||||
class Policy : noncopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Policy(const std::string& policyName);
|
||||
|
||||
virtual
|
||||
~Policy();
|
||||
|
||||
const std::string&
|
||||
getName() const;
|
||||
|
||||
public:
|
||||
/** \brief gets cs
|
||||
*/
|
||||
Cs*
|
||||
getCs() const;
|
||||
|
||||
/** \brief sets cs
|
||||
*/
|
||||
void
|
||||
setCs(Cs *cs);
|
||||
|
||||
/** \brief gets hard limit (in number of entries)
|
||||
*/
|
||||
size_t
|
||||
getLimit() const;
|
||||
|
||||
/** \brief sets hard limit (in number of entries)
|
||||
* \post getLimit() == nMaxEntries
|
||||
* \post cs.size() <= getLimit()
|
||||
*
|
||||
* The policy may evict entries if necessary.
|
||||
*/
|
||||
void
|
||||
setLimit(size_t nMaxEntries);
|
||||
|
||||
/** \brief emits when an entry is being evicted
|
||||
*
|
||||
* A policy implementation should emit this signal to cause CS to erase the entry from its index.
|
||||
* CS should connect to this signal and erase the entry upon signal emission.
|
||||
*/
|
||||
signal::Signal<Policy, iterator> beforeEvict;
|
||||
|
||||
/** \brief invoked by CS after a new entry is inserted
|
||||
* \post cs.size() <= getLimit()
|
||||
*
|
||||
* The policy may evict entries if necessary.
|
||||
* During this process, \p i might be evicted.
|
||||
*/
|
||||
void
|
||||
afterInsert(iterator i);
|
||||
|
||||
/** \brief invoked by CS after an existing entry is refreshed by same Data
|
||||
*
|
||||
* The policy may witness this refresh to make better eviction decisions in the future.
|
||||
*/
|
||||
void
|
||||
afterRefresh(iterator i);
|
||||
|
||||
/** \brief invoked by CS before an entry is erased due to management command
|
||||
* \warning CS must not invoke this method if an entry is erased due to eviction.
|
||||
*/
|
||||
void
|
||||
beforeErase(iterator i);
|
||||
|
||||
/** \brief invoked by CS before an entry is used to match a lookup
|
||||
*
|
||||
* The policy may witness this usage to make better eviction decisions in the future.
|
||||
*/
|
||||
void
|
||||
beforeUse(iterator i);
|
||||
|
||||
protected:
|
||||
/** \brief invoked after a new entry is created in CS
|
||||
*
|
||||
* When overridden in a subclass, a policy implementation should decide whether to accept \p i.
|
||||
* If \p i is accepted, it should be inserted into a cleanup index.
|
||||
* Otherwise, \p beforeEvict signal should be emitted with \p i to inform CS to erase the entry.
|
||||
* A policy implementation may decide to evict other entries by emitting \p beforeEvict signal,
|
||||
* in order to keep CS size under limit.
|
||||
*/
|
||||
virtual void
|
||||
doAfterInsert(iterator i) = 0;
|
||||
|
||||
/** \brief invoked after an existing entry is refreshed by same Data
|
||||
*
|
||||
* When overridden in a subclass, a policy implementation may witness this operation
|
||||
* and adjust its cleanup index.
|
||||
*/
|
||||
virtual void
|
||||
doAfterRefresh(iterator i) = 0;
|
||||
|
||||
/** \brief invoked before an entry is erased due to management command
|
||||
* \note This will not be invoked for an entry being evicted by policy.
|
||||
*
|
||||
* When overridden in a subclass, a policy implementation should erase \p i
|
||||
* from its cleanup index without emitted \p afterErase signal.
|
||||
*/
|
||||
virtual void
|
||||
doBeforeErase(iterator i) = 0;
|
||||
|
||||
/** \brief invoked before an entry is used to match a lookup
|
||||
*
|
||||
* When overridden in a subclass, a policy implementation may witness this operation
|
||||
* and adjust its cleanup index.
|
||||
*/
|
||||
virtual void
|
||||
doBeforeUse(iterator i) = 0;
|
||||
|
||||
/** \brief evicts zero or more entries
|
||||
* \post CS size does not exceed hard limit
|
||||
*/
|
||||
virtual void
|
||||
evictEntries() = 0;
|
||||
|
||||
protected:
|
||||
DECLARE_SIGNAL_EMIT(beforeEvict)
|
||||
|
||||
private:
|
||||
std::string m_policyName;
|
||||
size_t m_limit;
|
||||
Cs* m_cs;
|
||||
};
|
||||
|
||||
inline const std::string&
|
||||
Policy::getName() const
|
||||
{
|
||||
return m_policyName;
|
||||
}
|
||||
|
||||
inline Cs*
|
||||
Policy::getCs() const
|
||||
{
|
||||
return m_cs;
|
||||
}
|
||||
|
||||
inline void
|
||||
Policy::setCs(Cs *cs)
|
||||
{
|
||||
m_cs = cs;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
Policy::getLimit() const
|
||||
{
|
||||
return m_limit;
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_TABLE_CS_POLICY_HPP
|
||||
+58
-113
@@ -24,9 +24,9 @@
|
||||
*/
|
||||
|
||||
#include "cs.hpp"
|
||||
#include "cs-policy-priority-fifo.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/algorithm.hpp"
|
||||
#include <numeric>
|
||||
|
||||
NFD_LOG_INIT("ContentStore");
|
||||
|
||||
@@ -44,18 +44,38 @@ static_assert(std::is_default_constructible<Cs::const_iterator>::value,
|
||||
BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Cs::const_iterator>));
|
||||
#endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE
|
||||
|
||||
Cs::Cs(size_t nMaxPackets)
|
||||
: m_limit(nMaxPackets)
|
||||
unique_ptr<Policy>
|
||||
makeDefaultPolicy()
|
||||
{
|
||||
BOOST_ASSERT(nMaxPackets > 0);
|
||||
return unique_ptr<Policy>(new PriorityFifoPolicy());
|
||||
}
|
||||
|
||||
Cs::Cs(size_t nMaxPackets, unique_ptr<Policy> policy)
|
||||
{
|
||||
this->setPolicyImpl(policy);
|
||||
m_policy->setLimit(nMaxPackets);
|
||||
}
|
||||
|
||||
void
|
||||
Cs::setLimit(size_t nMaxPackets)
|
||||
{
|
||||
BOOST_ASSERT(nMaxPackets > 0);
|
||||
m_limit = nMaxPackets;
|
||||
this->evict();
|
||||
m_policy->setLimit(nMaxPackets);
|
||||
}
|
||||
|
||||
size_t
|
||||
Cs::getLimit() const
|
||||
{
|
||||
return m_policy->getLimit();
|
||||
}
|
||||
|
||||
void
|
||||
Cs::setPolicy(unique_ptr<Policy> policy)
|
||||
{
|
||||
BOOST_ASSERT(policy != nullptr);
|
||||
BOOST_ASSERT(m_policy != nullptr);
|
||||
size_t limit = m_policy->getLimit();
|
||||
this->setPolicyImpl(policy);
|
||||
m_policy->setLimit(limit);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -73,26 +93,25 @@ Cs::insert(const Data& data, bool isUnsolicited)
|
||||
}
|
||||
}
|
||||
|
||||
bool isNewEntry = false; TableIt it;
|
||||
bool isNewEntry = false;
|
||||
iterator it;
|
||||
// use .insert because gcc46 does not support .emplace
|
||||
std::tie(it, isNewEntry) = m_table.insert(EntryImpl(data.shared_from_this(), isUnsolicited));
|
||||
EntryImpl& entry = const_cast<EntryImpl&>(*it);
|
||||
|
||||
entry.updateStaleTime();
|
||||
|
||||
if (!isNewEntry) { // existing entry
|
||||
this->detachQueue(it);
|
||||
// XXX This doesn't forbid unsolicited Data from refreshing a solicited entry.
|
||||
if (entry.isUnsolicited() && !isUnsolicited) {
|
||||
entry.unsetUnsolicited();
|
||||
}
|
||||
|
||||
m_policy->afterRefresh(it);
|
||||
}
|
||||
else {
|
||||
m_policy->afterInsert(it);
|
||||
}
|
||||
entry.updateStaleTime();
|
||||
this->attachQueue(it);
|
||||
|
||||
// check there are same amount of entries in the table and in queues
|
||||
BOOST_ASSERT(m_table.size() == std::accumulate(m_queues, m_queues + QUEUE_MAX, 0U,
|
||||
[] (size_t sum, const Queue queue) { return sum + queue.size(); }));
|
||||
|
||||
this->evict(); // XXX The new entry could be evicted, but it shouldn't matter.
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -109,13 +128,13 @@ Cs::find(const Interest& interest,
|
||||
bool isRightmost = interest.getChildSelector() == 1;
|
||||
NFD_LOG_DEBUG("find " << prefix << (isRightmost ? " R" : " L"));
|
||||
|
||||
TableIt first = m_table.lower_bound(prefix);
|
||||
TableIt last = m_table.end();
|
||||
iterator first = m_table.lower_bound(prefix);
|
||||
iterator last = m_table.end();
|
||||
if (prefix.size() > 0) {
|
||||
last = m_table.lower_bound(prefix.getSuccessor());
|
||||
}
|
||||
|
||||
TableIt match = last;
|
||||
iterator match = last;
|
||||
if (isRightmost) {
|
||||
match = this->findRightmost(interest, first, last);
|
||||
}
|
||||
@@ -129,39 +148,40 @@ Cs::find(const Interest& interest,
|
||||
return;
|
||||
}
|
||||
NFD_LOG_DEBUG(" matching " << match->getName());
|
||||
m_policy->beforeUse(match);
|
||||
hitCallback(interest, match->getData());
|
||||
}
|
||||
|
||||
TableIt
|
||||
Cs::findLeftmost(const Interest& interest, TableIt first, TableIt last) const
|
||||
iterator
|
||||
Cs::findLeftmost(const Interest& interest, iterator first, iterator last) const
|
||||
{
|
||||
return std::find_if(first, last, bind(&cs::EntryImpl::canSatisfy, _1, interest));
|
||||
}
|
||||
|
||||
TableIt
|
||||
Cs::findRightmost(const Interest& interest, TableIt first, TableIt last) const
|
||||
iterator
|
||||
Cs::findRightmost(const Interest& interest, iterator first, iterator last) const
|
||||
{
|
||||
// Each loop visits a sub-namespace under a prefix one component longer than Interest Name.
|
||||
// If there is a match in that sub-namespace, the leftmost match is returned;
|
||||
// otherwise, loop continues.
|
||||
|
||||
size_t interestNameLength = interest.getName().size();
|
||||
for (TableIt right = last; right != first;) {
|
||||
TableIt prev = std::prev(right);
|
||||
for (iterator right = last; right != first;) {
|
||||
iterator prev = std::prev(right);
|
||||
|
||||
// special case: [first,prev] have exact Names
|
||||
if (prev->getName().size() == interestNameLength) {
|
||||
NFD_LOG_TRACE(" find-among-exact " << prev->getName());
|
||||
TableIt matchExact = this->findRightmostAmongExact(interest, first, right);
|
||||
iterator matchExact = this->findRightmostAmongExact(interest, first, right);
|
||||
return matchExact == right ? last : matchExact;
|
||||
}
|
||||
|
||||
Name prefix = prev->getName().getPrefix(interestNameLength + 1);
|
||||
TableIt left = m_table.lower_bound(prefix);
|
||||
iterator left = m_table.lower_bound(prefix);
|
||||
|
||||
// normal case: [left,right) are under one-component-longer prefix
|
||||
NFD_LOG_TRACE(" find-under-prefix " << prefix);
|
||||
TableIt match = this->findLeftmost(interest, left, right);
|
||||
iterator match = this->findLeftmost(interest, left, right);
|
||||
if (match != right) {
|
||||
return match;
|
||||
}
|
||||
@@ -170,97 +190,22 @@ Cs::findRightmost(const Interest& interest, TableIt first, TableIt last) const
|
||||
return last;
|
||||
}
|
||||
|
||||
TableIt
|
||||
Cs::findRightmostAmongExact(const Interest& interest, TableIt first, TableIt last) const
|
||||
iterator
|
||||
Cs::findRightmostAmongExact(const Interest& interest, iterator first, iterator last) const
|
||||
{
|
||||
return find_last_if(first, last, bind(&EntryImpl::canSatisfy, _1, interest));
|
||||
}
|
||||
|
||||
void
|
||||
Cs::attachQueue(TableIt it)
|
||||
Cs::setPolicyImpl(unique_ptr<Policy>& policy)
|
||||
{
|
||||
EntryImpl& entry = const_cast<EntryImpl&>(*it);
|
||||
m_policy = std::move(policy);
|
||||
m_beforeEvictConnection = m_policy->beforeEvict.connect([this] (iterator it) {
|
||||
m_table.erase(it);
|
||||
});
|
||||
|
||||
if (entry.queueType != QUEUE_NONE) {
|
||||
this->detachQueue(it);
|
||||
}
|
||||
|
||||
if (entry.isUnsolicited()) {
|
||||
entry.queueType = QUEUE_UNSOLICITED;
|
||||
}
|
||||
else if (entry.isStale()) {
|
||||
entry.queueType = QUEUE_STALE;
|
||||
}
|
||||
else {
|
||||
entry.queueType = QUEUE_FIFO;
|
||||
|
||||
if (entry.canStale()) {
|
||||
entry.moveStaleEvent = scheduler::schedule(entry.getData().getFreshnessPeriod(),
|
||||
bind(&Cs::moveToStaleQueue, this, it));
|
||||
}
|
||||
}
|
||||
|
||||
Queue& queue = m_queues[entry.queueType];
|
||||
entry.queueIt = queue.insert(queue.end(), it);
|
||||
}
|
||||
|
||||
void
|
||||
Cs::detachQueue(TableIt it)
|
||||
{
|
||||
EntryImpl& entry = const_cast<EntryImpl&>(*it);
|
||||
|
||||
BOOST_ASSERT(entry.queueType != QUEUE_NONE);
|
||||
|
||||
if (entry.queueType == QUEUE_FIFO) {
|
||||
scheduler::cancel(entry.moveStaleEvent);
|
||||
}
|
||||
|
||||
m_queues[entry.queueType].erase(entry.queueIt);
|
||||
entry.queueType = QUEUE_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
Cs::moveToStaleQueue(TableIt it)
|
||||
{
|
||||
EntryImpl& entry = const_cast<EntryImpl&>(*it);
|
||||
|
||||
BOOST_ASSERT(entry.queueType == QUEUE_FIFO);
|
||||
m_queues[QUEUE_FIFO].erase(entry.queueIt);
|
||||
|
||||
entry.queueType = QUEUE_STALE;
|
||||
Queue& queue = m_queues[QUEUE_STALE];
|
||||
entry.queueIt = queue.insert(queue.end(), it);
|
||||
}
|
||||
|
||||
std::tuple<TableIt, std::string>
|
||||
Cs::evictPick()
|
||||
{
|
||||
if (!m_queues[QUEUE_UNSOLICITED].empty()) {
|
||||
return std::make_tuple(m_queues[QUEUE_UNSOLICITED].front(), "unsolicited");
|
||||
}
|
||||
if (!m_queues[QUEUE_STALE].empty()) {
|
||||
return std::make_tuple(m_queues[QUEUE_STALE].front(), "stale");
|
||||
}
|
||||
if (!m_queues[QUEUE_FIFO].empty()) {
|
||||
return std::make_tuple(m_queues[QUEUE_FIFO].front(), "fifo");
|
||||
}
|
||||
|
||||
BOOST_ASSERT(false);
|
||||
return std::make_tuple(m_table.end(), "error");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Cs::evict()
|
||||
{
|
||||
while (this->size() > m_limit) {
|
||||
TableIt it; std::string reason;
|
||||
std::tie(it, reason) = this->evictPick();
|
||||
|
||||
NFD_LOG_DEBUG("evict " << it->getName() << " " << reason);
|
||||
this->detachQueue(it);
|
||||
m_table.erase(it);
|
||||
}
|
||||
m_policy->setCs(this);
|
||||
BOOST_ASSERT(m_policy->getCs() == this);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+30
-39
@@ -48,19 +48,25 @@
|
||||
#ifndef NFD_DAEMON_TABLE_CS_HPP
|
||||
#define NFD_DAEMON_TABLE_CS_HPP
|
||||
|
||||
#include "cs-policy.hpp"
|
||||
#include "cs-internal.hpp"
|
||||
#include "cs-entry-impl.hpp"
|
||||
#include <ndn-cxx/util/signal.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
|
||||
unique_ptr<Policy>
|
||||
makeDefaultPolicy();
|
||||
|
||||
/** \brief represents the ContentStore
|
||||
*/
|
||||
class Cs : noncopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Cs(size_t nMaxPackets = 10);
|
||||
Cs(size_t nMaxPackets = 10, unique_ptr<Policy> policy = makeDefaultPolicy());
|
||||
|
||||
/** \brief inserts a Data packet
|
||||
* \return true
|
||||
@@ -97,9 +103,20 @@ public:
|
||||
/** \return capacity (in number of packets)
|
||||
*/
|
||||
size_t
|
||||
getLimit() const
|
||||
getLimit() const;
|
||||
|
||||
/** \brief changes cs replacement policy
|
||||
* \pre size() == 0
|
||||
*/
|
||||
void
|
||||
setPolicy(unique_ptr<Policy> policy);
|
||||
|
||||
/** \return cs replacement policy
|
||||
*/
|
||||
Policy*
|
||||
getPolicy() const
|
||||
{
|
||||
return m_limit;
|
||||
return m_policy.get();
|
||||
}
|
||||
|
||||
/** \return number of stored packets
|
||||
@@ -128,7 +145,7 @@ public: // enumeration
|
||||
|
||||
/** \brief ContentStore iterator (public API)
|
||||
*/
|
||||
typedef boost::transform_iterator<EntryFromEntryImpl, TableIt, const Entry&> const_iterator;
|
||||
typedef boost::transform_iterator<EntryFromEntryImpl, iterator, const Entry&> const_iterator;
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
@@ -146,54 +163,28 @@ private: // find
|
||||
/** \brief find leftmost match in [first,last)
|
||||
* \return the leftmost match, or last if not found
|
||||
*/
|
||||
TableIt
|
||||
findLeftmost(const Interest& interest, TableIt left, TableIt right) const;
|
||||
iterator
|
||||
findLeftmost(const Interest& interest, iterator left, iterator right) const;
|
||||
|
||||
/** \brief find rightmost match in [first,last)
|
||||
* \return the rightmost match, or last if not found
|
||||
*/
|
||||
TableIt
|
||||
findRightmost(const Interest& interest, TableIt first, TableIt last) const;
|
||||
iterator
|
||||
findRightmost(const Interest& interest, iterator first, iterator last) const;
|
||||
|
||||
/** \brief find rightmost match among entries with exact Names in [first,last)
|
||||
* \return the rightmost match, or last if not found
|
||||
*/
|
||||
TableIt
|
||||
findRightmostAmongExact(const Interest& interest, TableIt first, TableIt last) const;
|
||||
iterator
|
||||
findRightmostAmongExact(const Interest& interest, iterator first, iterator last) const;
|
||||
|
||||
private: // cleanup
|
||||
/** \brief attaches an entry to a suitable cleanup queue
|
||||
* \note if the entry is already attached to a queue, it's automatically detached
|
||||
*/
|
||||
void
|
||||
attachQueue(TableIt it);
|
||||
|
||||
/** \brief detaches an entry from its current cleanup queue
|
||||
* \warning if the entry is unattached, this will cause undefined behavior
|
||||
*/
|
||||
void
|
||||
detachQueue(TableIt it);
|
||||
|
||||
/** \brief moves an entry from FIFO queue to STALE queue
|
||||
*/
|
||||
void
|
||||
moveToStaleQueue(TableIt it);
|
||||
|
||||
/** \brief picks an entry for eviction
|
||||
*/
|
||||
std::tuple<TableIt, std::string/*reason*/>
|
||||
evictPick();
|
||||
|
||||
/** \brief evicts zero or more entries so that number of stored entries
|
||||
* is not greater than capacity
|
||||
*/
|
||||
void
|
||||
evict();
|
||||
setPolicyImpl(unique_ptr<Policy>& policy);
|
||||
|
||||
private:
|
||||
size_t m_limit;
|
||||
Table m_table;
|
||||
Queue m_queues[QUEUE_MAX];
|
||||
unique_ptr<Policy> m_policy;
|
||||
ndn::util::signal::ScopedConnection m_beforeEvictConnection;
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
@@ -3,6 +3,51 @@
|
||||
NFD Release Notes
|
||||
=================
|
||||
|
||||
NFD version 0.3.3 (changes since version 0.3.2)
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Release date: July 1, 2015
|
||||
|
||||
New features:
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- Content Store replacement policy interface (:issue:`1207`)
|
||||
|
||||
- Add unit file and instructions for systemd (:issue:`1586`)
|
||||
|
||||
- NDN Essential Tools version 0.1 `<https://github.com/named-data/ndn-tools>`__ featuring:
|
||||
|
||||
* ``ndnpeek``, ``ndnpoke``: a pair of programs to request and make available for retrieval of
|
||||
a single Data packet
|
||||
* ``ndnping``, ``ndnpingserver``: reachability testing tools for Named Data Networking
|
||||
* ``ndndump``: a traffic analysis tool that captures Interest and Data packets on the wire
|
||||
* ``ndn-dissect``: an NDN packet format inspector. It reads zero or more NDN packets from
|
||||
either an input file or the standard input, and displays the Type-Length-Value (TLV)
|
||||
structure of those packets on the standard output.
|
||||
|
||||
Updates and bug fixes:
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Avoid loopback new Interest in AccessStrategy (:issue:`2831`)
|
||||
|
||||
- Simplified implementation of ``nfd-status`` using SegmentFetcher utility class (:issue:`2456`)
|
||||
|
||||
Deprecated:
|
||||
^^^^^^^^^^^
|
||||
|
||||
- ``ndn-tlv-peek`` and ``ndn-tlv-poke`` command-line tools: use ``ndnpeek`` and ``ndnpoke``
|
||||
programs from NDN Essential Tools repository `<https://github.com/named-data/ndn-tools>`__.
|
||||
|
||||
Upcoming features:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- NDNLPv2 (http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2, :issue:`2520`,
|
||||
:issue:`2879`, :issue:`2763`, :issue:`2883`, :issue:`2841`, :issue:`2866`)
|
||||
|
||||
- Refactored implementation of NFD management (:issue:`2200`, :issue:`2107`)
|
||||
|
||||
****************************************************************************
|
||||
|
||||
NFD version 0.3.2 (changes since version 0.3.1)
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
ndn-tlv-peek
|
||||
============
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
ndn-tlv-peek is deprecated and will be removed in a future release of NFD.
|
||||
Please use ``ndnpeek`` program from ndn-tools repository `<https://github.com/named-data/ndn-tools>`__.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
ndn-tlv-poke
|
||||
============
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
ndn-tlv-poke is deprecated and will be removed in a future release of NFD.
|
||||
Please use ``ndnpoke`` program from ndn-tools repository `<https://github.com/named-data/ndn-tools>`__.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Options
|
||||
Expiration time of the RIB entry in milliseconds. If not specified, the entry remains in FIB
|
||||
for the lifetime of the associated face.
|
||||
|
||||
``-o <origin>``
|
||||
``-o <origin>``
|
||||
Origin of the registration request (default is 255).
|
||||
0 for Local producer applications, 128 for NLSR, 255 for static routes.
|
||||
|
||||
@@ -62,10 +62,10 @@ Options
|
||||
|
||||
``unregister [-o origin] <prefix> <faceId>``
|
||||
|
||||
``-o <origin>``
|
||||
``-o <origin>``
|
||||
Origin of the unregistration request (default is 255).
|
||||
|
||||
``prefix``
|
||||
``prefix``
|
||||
A prefix of an existing RIB entry, from which routing entry is requested to be
|
||||
removed.
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "remote-registrator.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
#include <ndn-cxx/security/signing-helpers.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
@@ -196,7 +197,7 @@ RemoteRegistrator::registerPrefix(const Name& prefix)
|
||||
CommandOptions options = m_commandOptions;
|
||||
|
||||
startRegistration(parameters.setName(prefixForRegistration),
|
||||
options.setSigningIdentity(identity.first),
|
||||
options.setSigningInfo(signingByIdentity(identity.first)),
|
||||
m_nRetries);
|
||||
}
|
||||
|
||||
@@ -268,7 +269,7 @@ RemoteRegistrator::unregisterPrefix(const Name& prefix)
|
||||
CommandOptions options = m_commandOptions;
|
||||
|
||||
startUnregistration(parameters.setName(prefixForRegistration).unsetCost(),
|
||||
options.setSigningIdentity(identity.first),
|
||||
options.setSigningInfo(signingByIdentity(identity.first)),
|
||||
m_nRetries);
|
||||
}
|
||||
|
||||
@@ -427,7 +428,7 @@ RemoteRegistrator::redoRegistration()
|
||||
ControlParameters parameters = m_controlParameters;
|
||||
CommandOptions options = m_commandOptions;
|
||||
startRegistration(parameters.setName(entry.first),
|
||||
options.setSigningIdentity(entry.first),
|
||||
options.setSigningInfo(signingByIdentity(entry.first)),
|
||||
m_nRetries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ protected:
|
||||
size_t totalLength = 0;
|
||||
for (int64_t i = 0; i < N; i++)
|
||||
{
|
||||
totalLength += ndn::prependNonNegativeIntegerBlock(outBuffer, tlv::Content, i);
|
||||
totalLength += prependNonNegativeIntegerBlock(outBuffer, tlv::Content, i);
|
||||
}
|
||||
m_totalPayloadLength += totalLength;
|
||||
return totalLength;
|
||||
|
||||
@@ -53,10 +53,7 @@ public:
|
||||
wireEncode() const
|
||||
{
|
||||
ndn::EncodingBuffer buffer;
|
||||
ndn::prependByteArrayBlock(buffer,
|
||||
0x8888,
|
||||
reinterpret_cast<const uint8_t*>(m_message.c_str()),
|
||||
m_message.size());
|
||||
prependStringBlock(buffer, 0x8888, m_message);
|
||||
return buffer.block();
|
||||
}
|
||||
|
||||
|
||||
@@ -350,6 +350,23 @@ BOOST_FIXTURE_TEST_CASE(PacketLoss, TwoLaptopsFixture)
|
||||
BOOST_CHECK_EQUAL(hasData2c, true);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(Bug2831, TwoLaptopsFixture)
|
||||
{
|
||||
// make a two-node loop
|
||||
topo.registerPrefix(laptopA, linkA->getFace(laptopA), "ndn:/net");
|
||||
topo.registerPrefix(router, linkA->getFace(router), "ndn:/net");
|
||||
|
||||
// send Interests from laptopA to router
|
||||
shared_ptr<TopologyAppLink> consumer = topo.addAppFace(laptopA);
|
||||
topo.addIntervalConsumer(*consumer->getClientFace(), "ndn:/net",
|
||||
time::milliseconds(100), 10);
|
||||
|
||||
this->advanceClocks(time::milliseconds(5), time::seconds(2));
|
||||
|
||||
// Interest shouldn't loop back from router
|
||||
BOOST_CHECK_EQUAL(linkA->getFace(router)->m_sentInterests.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace tests
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "table/cs.hpp"
|
||||
#include "table/cs-policy-priority-fifo.hpp"
|
||||
#include <ndn-cxx/util/crypto.hpp>
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
namespace tests {
|
||||
|
||||
using namespace nfd::tests;
|
||||
using ndn::nfd::LocalControlHeader;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(CsPriorityFifo)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(EvictOne, UnitTestTimeFixture)
|
||||
{
|
||||
Cs cs(3);
|
||||
cs.setPolicy(unique_ptr<Policy>(new PriorityFifoPolicy()));
|
||||
|
||||
shared_ptr<Data> dataA = makeData("ndn:/A");
|
||||
dataA->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataA->wireEncode();
|
||||
cs.insert(*dataA);
|
||||
|
||||
shared_ptr<Data> dataB = makeData("ndn:/B");
|
||||
dataB->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataB->wireEncode();
|
||||
cs.insert(*dataB);
|
||||
|
||||
shared_ptr<Data> dataC = makeData("ndn:/C");
|
||||
dataC->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataC->wireEncode();
|
||||
cs.insert(*dataC, true);
|
||||
|
||||
this->advanceClocks(time::milliseconds(11));
|
||||
|
||||
// evict unsolicited
|
||||
shared_ptr<Data> dataD = makeData("ndn:/D");
|
||||
dataD->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataD->wireEncode();
|
||||
cs.insert(*dataD);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
|
||||
// evict stale
|
||||
shared_ptr<Data> dataE = makeData("ndn:/E");
|
||||
dataE->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataE->wireEncode();
|
||||
cs.insert(*dataE);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/B"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
|
||||
// evict fifo
|
||||
shared_ptr<Data> dataF = makeData("ndn:/F");
|
||||
dataF->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataF->wireEncode();
|
||||
cs.insert(*dataF);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/A"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(Refresh, UnitTestTimeFixture)
|
||||
{
|
||||
Cs cs(3);
|
||||
cs.setPolicy(unique_ptr<Policy>(new PriorityFifoPolicy()));
|
||||
|
||||
shared_ptr<Data> dataA = makeData("ndn:/A");
|
||||
dataA->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataA->wireEncode();
|
||||
cs.insert(*dataA);
|
||||
|
||||
shared_ptr<Data> dataB = makeData("ndn:/B");
|
||||
dataB->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataB->wireEncode();
|
||||
cs.insert(*dataB);
|
||||
|
||||
shared_ptr<Data> dataC = makeData("ndn:/C");
|
||||
dataC->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataC->wireEncode();
|
||||
cs.insert(*dataC);
|
||||
|
||||
this->advanceClocks(time::milliseconds(11));
|
||||
|
||||
// refresh dataB
|
||||
shared_ptr<Data> dataB2 = make_shared<Data>(*dataB);
|
||||
dataB2->wireEncode();
|
||||
cs.insert(*dataB2);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/A"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
cs.find(Interest("ndn:/B"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
// evict dataC stale
|
||||
shared_ptr<Data> dataD = makeData("ndn:/D");
|
||||
dataD->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataD->wireEncode();
|
||||
cs.insert(*dataD);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace tests
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
@@ -330,107 +330,6 @@ BOOST_AUTO_TEST_CASE(CachingPolicyNoCache)
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(Evict, UnitTestTimeFixture)
|
||||
{
|
||||
Cs cs(3);
|
||||
|
||||
shared_ptr<Data> dataA = makeData("ndn:/A");
|
||||
dataA->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataA->wireEncode();
|
||||
cs.insert(*dataA);
|
||||
|
||||
shared_ptr<Data> dataB = makeData("ndn:/B");
|
||||
dataB->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataB->wireEncode();
|
||||
cs.insert(*dataB);
|
||||
|
||||
shared_ptr<Data> dataC = makeData("ndn:/C");
|
||||
dataC->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataC->wireEncode();
|
||||
cs.insert(*dataC, true);
|
||||
|
||||
this->advanceClocks(time::milliseconds(11));
|
||||
|
||||
// evict unsolicited
|
||||
shared_ptr<Data> dataD = makeData("ndn:/D");
|
||||
dataD->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataD->wireEncode();
|
||||
cs.insert(*dataD);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
|
||||
// evict stale
|
||||
shared_ptr<Data> dataE = makeData("ndn:/E");
|
||||
dataE->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataE->wireEncode();
|
||||
cs.insert(*dataE);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/B"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
|
||||
// evict fifo
|
||||
shared_ptr<Data> dataF = makeData("ndn:/F");
|
||||
dataF->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataF->wireEncode();
|
||||
cs.insert(*dataF);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/A"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(Refresh, UnitTestTimeFixture)
|
||||
{
|
||||
Cs cs(3);
|
||||
|
||||
shared_ptr<Data> dataA = makeData("ndn:/A");
|
||||
dataA->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataA->wireEncode();
|
||||
cs.insert(*dataA);
|
||||
|
||||
shared_ptr<Data> dataB = makeData("ndn:/B");
|
||||
dataB->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataB->wireEncode();
|
||||
cs.insert(*dataB);
|
||||
|
||||
shared_ptr<Data> dataC = makeData("ndn:/C");
|
||||
dataC->setFreshnessPeriod(time::milliseconds(10));
|
||||
dataC->wireEncode();
|
||||
cs.insert(*dataC);
|
||||
|
||||
this->advanceClocks(time::milliseconds(11));
|
||||
|
||||
// refresh dataB
|
||||
shared_ptr<Data> dataB2 = make_shared<Data>(*dataB);
|
||||
dataB2->wireEncode();
|
||||
cs.insert(*dataB2);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/A"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
cs.find(Interest("ndn:/B"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(true); }),
|
||||
bind([] { BOOST_CHECK(false); }));
|
||||
|
||||
// evict dataC stale
|
||||
shared_ptr<Data> dataD = makeData("ndn:/D");
|
||||
dataD->setFreshnessPeriod(time::milliseconds(99999));
|
||||
dataD->wireEncode();
|
||||
cs.insert(*dataD);
|
||||
BOOST_CHECK_EQUAL(cs.size(), 3);
|
||||
cs.find(Interest("ndn:/C"),
|
||||
bind([] { BOOST_CHECK(false); }),
|
||||
bind([] { BOOST_CHECK(true); }));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Enumeration)
|
||||
{
|
||||
Cs cs;
|
||||
|
||||
+10
-9
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -21,8 +21,6 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#include "version.hpp"
|
||||
@@ -226,6 +224,9 @@ private:
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
std::cerr << "ndn-tlv-peek is deprecated. Use ndnpeek program from ndn-tools repository.\n"
|
||||
"See `man ndn-tlv-peek` for details." << std::endl;
|
||||
|
||||
ndntlvpeek::NdnTlvPeek ndnTlvPeek(argv[0]);
|
||||
int option;
|
||||
while ((option = getopt(argc, argv, "hfrm:M:l:pw:V")) != -1) {
|
||||
|
||||
+10
-9
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -21,8 +21,6 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
|
||||
*/
|
||||
|
||||
#include "version.hpp"
|
||||
@@ -227,6 +225,9 @@ private:
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
std::cerr << "ndn-tlv-poke is deprecated. Use ndnpoke program from ndn-tools repository.\n"
|
||||
"See `man ndn-tlv-poke` for details." << std::endl;
|
||||
|
||||
int option;
|
||||
ndntlvpoke::NdnTlvPoke ndnTlvPoke(argv[0]);
|
||||
while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
|
||||
|
||||
+54
-67
@@ -38,12 +38,15 @@
|
||||
#include <ndn-cxx/management/nfd-fib-entry.hpp>
|
||||
#include <ndn-cxx/management/nfd-rib-entry.hpp>
|
||||
#include <ndn-cxx/management/nfd-strategy-choice.hpp>
|
||||
#include <ndn-cxx/util/segment-fetcher.hpp>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <list>
|
||||
|
||||
namespace ndn {
|
||||
|
||||
using util::SegmentFetcher;
|
||||
|
||||
class NfdStatus
|
||||
{
|
||||
public:
|
||||
@@ -132,26 +135,13 @@ public:
|
||||
runNextStep();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fetchSegments(const Data& data, void (NfdStatus::*onDone)())
|
||||
onErrorFetch(uint32_t errorCode, const std::string& errorMsg)
|
||||
{
|
||||
m_buffer->write((const char*)data.getContent().value(),
|
||||
data.getContent().value_size());
|
||||
std::cerr << "Error code:" << errorCode << ", message:" << errorMsg << std::endl;
|
||||
|
||||
uint64_t currentSegment = data.getName().get(-1).toSegment();
|
||||
|
||||
const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
|
||||
if (finalBlockId.empty() ||
|
||||
finalBlockId.toSegment() > currentSegment)
|
||||
{
|
||||
m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
|
||||
bind(&NfdStatus::fetchSegments, this, _2, onDone),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (this->*onDone)();
|
||||
}
|
||||
runNextStep();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -277,24 +267,23 @@ public:
|
||||
interest.setChildSelector(1);
|
||||
interest.setMustBeFresh(true);
|
||||
|
||||
m_face.expressInterest(interest,
|
||||
bind(&NfdStatus::fetchSegments, this, _2,
|
||||
&NfdStatus::afterFetchedChannelStatusInformation),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
SegmentFetcher::fetch(m_face, interest,
|
||||
util::DontVerifySegment(),
|
||||
bind(&NfdStatus::afterFetchedChannelStatusInformation, this, _1),
|
||||
bind(&NfdStatus::onErrorFetch, this, _1, _2));
|
||||
}
|
||||
|
||||
void
|
||||
afterFetchedChannelStatusInformation()
|
||||
afterFetchedChannelStatusInformation(const ConstBufferPtr& dataset)
|
||||
{
|
||||
ConstBufferPtr buf = m_buffer->buf();
|
||||
if (m_isOutputXml) {
|
||||
std::cout << "<channels>";
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
|
||||
break;
|
||||
@@ -317,10 +306,10 @@ public:
|
||||
std::cout << "Channels:" << std::endl;
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
|
||||
break;
|
||||
@@ -348,24 +337,23 @@ public:
|
||||
interest.setChildSelector(1);
|
||||
interest.setMustBeFresh(true);
|
||||
|
||||
m_face.expressInterest(interest,
|
||||
bind(&NfdStatus::fetchSegments, this, _2,
|
||||
&NfdStatus::afterFetchedFaceStatusInformation),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
SegmentFetcher::fetch(m_face, interest,
|
||||
util::DontVerifySegment(),
|
||||
bind(&NfdStatus::afterFetchedFaceStatusInformation, this, _1),
|
||||
bind(&NfdStatus::onErrorFetch, this, _1, _2));
|
||||
}
|
||||
|
||||
void
|
||||
afterFetchedFaceStatusInformation()
|
||||
afterFetchedFaceStatusInformation(const ConstBufferPtr& dataset)
|
||||
{
|
||||
ConstBufferPtr buf = m_buffer->buf();
|
||||
if (m_isOutputXml) {
|
||||
std::cout << "<faces>";
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
|
||||
break;
|
||||
@@ -430,10 +418,10 @@ public:
|
||||
std::cout << "Faces:" << std::endl;
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
|
||||
break;
|
||||
@@ -480,24 +468,24 @@ public:
|
||||
Interest interest("/localhost/nfd/fib/list");
|
||||
interest.setChildSelector(1);
|
||||
interest.setMustBeFresh(true);
|
||||
m_face.expressInterest(interest,
|
||||
bind(&NfdStatus::fetchSegments, this, _2,
|
||||
&NfdStatus::afterFetchedFibEnumerationInformation),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
|
||||
SegmentFetcher::fetch(m_face, interest,
|
||||
util::DontVerifySegment(),
|
||||
bind(&NfdStatus::afterFetchedFibEnumerationInformation, this, _1),
|
||||
bind(&NfdStatus::onErrorFetch, this, _1, _2));
|
||||
}
|
||||
|
||||
void
|
||||
afterFetchedFibEnumerationInformation()
|
||||
afterFetchedFibEnumerationInformation(const ConstBufferPtr& dataset)
|
||||
{
|
||||
ConstBufferPtr buf = m_buffer->buf();
|
||||
if (m_isOutputXml) {
|
||||
std::cout << "<fib>";
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode FibEntry TLV";
|
||||
break;
|
||||
@@ -527,10 +515,10 @@ public:
|
||||
std::cout << "FIB:" << std::endl;
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
|
||||
break;
|
||||
@@ -568,24 +556,24 @@ public:
|
||||
Interest interest("/localhost/nfd/strategy-choice/list");
|
||||
interest.setChildSelector(1);
|
||||
interest.setMustBeFresh(true);
|
||||
m_face.expressInterest(interest,
|
||||
bind(&NfdStatus::fetchSegments, this, _2,
|
||||
&NfdStatus::afterFetchedStrategyChoiceInformationInformation),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
|
||||
SegmentFetcher::fetch(m_face, interest,
|
||||
util::DontVerifySegment(),
|
||||
bind(&NfdStatus::afterFetchedStrategyChoiceInformationInformation, this, _1),
|
||||
bind(&NfdStatus::onErrorFetch, this, _1, _2));
|
||||
}
|
||||
|
||||
void
|
||||
afterFetchedStrategyChoiceInformationInformation()
|
||||
afterFetchedStrategyChoiceInformationInformation(const ConstBufferPtr& dataset)
|
||||
{
|
||||
ConstBufferPtr buf = m_buffer->buf();
|
||||
if (m_isOutputXml) {
|
||||
std::cout << "<strategyChoices>";
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode StrategyChoice TLV";
|
||||
break;
|
||||
@@ -615,10 +603,10 @@ public:
|
||||
std::cout << "Strategy choices:" << std::endl;
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
|
||||
break;
|
||||
@@ -644,24 +632,23 @@ public:
|
||||
interest.setChildSelector(1);
|
||||
interest.setMustBeFresh(true);
|
||||
|
||||
m_face.expressInterest(interest,
|
||||
bind(&NfdStatus::fetchSegments, this, _2,
|
||||
&NfdStatus::afterFetchedRibStatusInformation),
|
||||
bind(&NfdStatus::onTimeout, this));
|
||||
SegmentFetcher::fetch(m_face, interest,
|
||||
util::DontVerifySegment(),
|
||||
bind(&NfdStatus::afterFetchedRibStatusInformation, this, _1),
|
||||
bind(&NfdStatus::onErrorFetch, this, _1, _2));
|
||||
}
|
||||
|
||||
void
|
||||
afterFetchedRibStatusInformation()
|
||||
afterFetchedRibStatusInformation(const ConstBufferPtr& dataset)
|
||||
{
|
||||
ConstBufferPtr buf = m_buffer->buf();
|
||||
if (m_isOutputXml) {
|
||||
std::cout << "<rib>";
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode RibEntry TLV";
|
||||
break;
|
||||
@@ -706,10 +693,10 @@ public:
|
||||
std::cout << "RIB:" << std::endl;
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < buf->size()) {
|
||||
while (offset < dataset->size()) {
|
||||
bool isOk = false;
|
||||
Block block;
|
||||
std::tie(isOk, block) = Block::fromBuffer(buf, offset);
|
||||
std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
|
||||
if (!isOk) {
|
||||
std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
|
||||
break;
|
||||
|
||||
@@ -24,7 +24,7 @@ You should have received a copy of the GNU General Public License along with
|
||||
NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
VERSION = "0.3.2"
|
||||
VERSION = "0.3.3"
|
||||
APPNAME = "nfd"
|
||||
BUGREPORT = "http://redmine.named-data.net/projects/nfd"
|
||||
URL = "http://named-data.net/doc/NFD/"
|
||||
|
||||
Reference in new issue
Block a user