face: EthernetTransport
This commit replaces NDNLPv1 fragmentation and reassembly
with NDNLPv2 fragmentation and reassembly.
Change-Id: I10751157fcced94d441167ce470aaed79c12bb54
Refs: #3170
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index 3d88590..3592530 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -24,16 +24,16 @@
*/
#include "ethernet-factory.hpp"
-#include "face/ethernet-face.hpp"
-
-#include "core/logger.hpp"
+#include "ethernet-transport.hpp"
+#include "generic-link-service.hpp"
+#include "lp-face-wrapper.hpp"
#include "core/global-io.hpp"
namespace nfd {
-shared_ptr<EthernetFace>
+shared_ptr<face::LpFaceWrapper>
EthernetFactory::createMulticastFace(const NetworkInterfaceInfo& interface,
- const ethernet::Address &address)
+ const ethernet::Address& address)
{
if (!address.isMulticast())
BOOST_THROW_EXCEPTION(Error(address.toString() + " is not a multicast address"));
@@ -42,8 +42,14 @@
if (face)
return face;
- face = make_shared<EthernetFace>(boost::asio::posix::stream_descriptor(getGlobalIoService()),
- interface, address);
+ face::GenericLinkService::Options opts;
+ opts.allowFragmentation = true;
+ opts.allowReassembly = true;
+
+ auto linkService = make_unique<face::GenericLinkService>(opts);
+ auto transport = make_unique<face::EthernetTransport>(interface, address);
+ auto lpFace = make_unique<face::LpFace>(std::move(linkService), std::move(transport));
+ face = make_shared<face::LpFaceWrapper>(std::move(lpFace));
auto key = std::make_pair(interface.name, address);
face->onFail.connectSingleShot([this, key] (const std::string& reason) {
@@ -69,7 +75,7 @@
return {};
}
-shared_ptr<EthernetFace>
+shared_ptr<face::LpFaceWrapper>
EthernetFactory::findMulticastFace(const std::string& interfaceName,
const ethernet::Address& address) const
{
diff --git a/daemon/face/ethernet-factory.hpp b/daemon/face/ethernet-factory.hpp
index c14e093..c0a951d 100644
--- a/daemon/face/ethernet-factory.hpp
+++ b/daemon/face/ethernet-factory.hpp
@@ -31,7 +31,9 @@
namespace nfd {
-class EthernetFace;
+namespace face {
+class LpFaceWrapper;
+} // namespace face
class EthernetFactory : public ProtocolFactory
{
@@ -50,7 +52,7 @@
};
typedef std::map<std::pair<std::string, ethernet::Address>,
- shared_ptr<EthernetFace>> MulticastFaceMap;
+ shared_ptr<face::LpFaceWrapper>> MulticastFaceMap;
/**
* \brief Create an EthernetFace to communicate with the given multicast group
@@ -65,9 +67,9 @@
* \returns always a valid shared pointer to an EthernetFace object,
* an exception will be thrown if the creation fails
*
- * \throws EthernetFactory::Error or EthernetFace::Error
+ * \throws EthernetFactory::Error or EthernetTransport::Error
*/
- shared_ptr<EthernetFace>
+ shared_ptr<face::LpFaceWrapper>
createMulticastFace(const NetworkInterfaceInfo& interface,
const ethernet::Address& address);
@@ -94,7 +96,7 @@
* \returns shared pointer to the existing EthernetFace object
* or nullptr when such face does not exist
*/
- shared_ptr<EthernetFace>
+ shared_ptr<face::LpFaceWrapper>
findMulticastFace(const std::string& interfaceName,
const ethernet::Address& address) const;
diff --git a/daemon/face/ethernet-face.cpp b/daemon/face/ethernet-transport.cpp
similarity index 62%
rename from daemon/face/ethernet-face.cpp
rename to daemon/face/ethernet-transport.cpp
index f31a8f6..5318097 100644
--- a/daemon/face/ethernet-face.cpp
+++ b/daemon/face/ethernet-transport.cpp
@@ -23,17 +23,17 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ethernet-face.hpp"
+#include "ethernet-transport.hpp"
#include "core/global-io.hpp"
#include <pcap/pcap.h>
#include <cerrno> // for errno
-#include <cstring> // for std::strerror() and std::strncpy()
-#include <stdio.h> // for snprintf()
+#include <cstring> // for memcpy(), strerror(), strncpy()
#include <arpa/inet.h> // for htons() and ntohs()
#include <net/ethernet.h> // for struct ether_header
#include <net/if.h> // for struct ifreq
+#include <stdio.h> // for snprintf()
#include <sys/ioctl.h> // for ioctl()
#include <unistd.h> // for dup()
@@ -57,28 +57,32 @@
#endif
namespace nfd {
+namespace face {
-NFD_LOG_INIT("EthernetFace");
+NFD_LOG_INIT("EthernetTransport");
-const time::nanoseconds EthernetFace::REASSEMBLER_LIFETIME = time::seconds(60);
-
-EthernetFace::EthernetFace(boost::asio::posix::stream_descriptor socket,
- const NetworkInterfaceInfo& interface,
- const ethernet::Address& address)
- : Face(FaceUri(address), FaceUri::fromDev(interface.name), false, true)
- , m_pcap(nullptr, pcap_close)
- , m_socket(std::move(socket))
+EthernetTransport::EthernetTransport(const NetworkInterfaceInfo& interface,
+ const ethernet::Address& mcastAddress)
+ : m_pcap(nullptr, pcap_close)
+ , m_socket(getGlobalIoService())
+ , m_srcAddress(interface.etherAddress)
+ , m_destAddress(mcastAddress)
+ , m_interfaceName(interface.name)
#if defined(__linux__)
, m_interfaceIndex(interface.index)
#endif
- , m_interfaceName(interface.name)
- , m_srcAddress(interface.etherAddress)
- , m_destAddress(address)
#ifdef _DEBUG
, m_nDropped(0)
#endif
{
- NFD_LOG_FACE_INFO("Creating face on " << m_interfaceName << "/" << m_srcAddress);
+ this->setLocalUri(FaceUri::fromDev(interface.name));
+ this->setRemoteUri(FaceUri(mcastAddress));
+ this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
+ this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
+ this->setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
+
+ NFD_LOG_FACE_INFO("Creating transport");
+
pcapInit();
int fd = pcap_get_selectable_fd(m_pcap.get());
@@ -90,10 +94,8 @@
// same fd and one of them will fail
m_socket.assign(::dup(fd));
- m_interfaceMtu = getInterfaceMtu();
- NFD_LOG_FACE_DEBUG("Interface MTU is: " << m_interfaceMtu);
-
- m_slicer.reset(new ndnlp::Slicer(m_interfaceMtu));
+ // do this after assigning m_socket because getInterfaceMtu uses it
+ this->setMtu(getInterfaceMtu());
char filter[100];
// std::snprintf not found in some environments
@@ -105,62 +107,54 @@
m_srcAddress.toString().c_str());
setPacketFilter(filter);
- if (!m_destAddress.isBroadcast() && !joinMulticastGroup())
- {
- NFD_LOG_FACE_WARN("Falling back to promiscuous mode");
- pcap_set_promisc(m_pcap.get(), 1);
- }
+ if (!m_destAddress.isBroadcast() && !joinMulticastGroup()) {
+ NFD_LOG_FACE_WARN("Falling back to promiscuous mode");
+ pcap_set_promisc(m_pcap.get(), 1);
+ }
m_socket.async_read_some(boost::asio::null_buffers(),
- bind(&EthernetFace::handleRead, this,
+ bind(&EthernetTransport::handleRead, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
-void
-EthernetFace::sendInterest(const Interest& interest)
+void EthernetTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
{
- NFD_LOG_FACE_TRACE(__func__);
-
- this->emitSignal(onSendInterest, interest);
-
- ndnlp::PacketArray pa = m_slicer->slice(interest.wireEncode());
- for (const auto& packet : *pa) {
- sendPacket(packet);
+ if (newPersistency != ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
+ BOOST_THROW_EXCEPTION(
+ std::invalid_argument("EthernetTransport supports only FACE_PERSISTENCY_PERMANENT"));
}
}
-void
-EthernetFace::sendData(const Data& data)
+void EthernetTransport::doSend(Transport::Packet&& packet)
{
NFD_LOG_FACE_TRACE(__func__);
- this->emitSignal(onSendData, data);
-
- ndnlp::PacketArray pa = m_slicer->slice(data.wireEncode());
- for (const auto& packet : *pa) {
- sendPacket(packet);
- }
+ sendPacket(packet.packet);
}
-void
-EthernetFace::close()
+void EthernetTransport::doClose()
{
- if (!m_pcap)
- return;
+ NFD_LOG_FACE_TRACE(__func__);
- NFD_LOG_FACE_INFO("Closing face");
-
- boost::system::error_code error;
- m_socket.cancel(error); // ignore errors
- m_socket.close(error); // ignore errors
+ if (m_socket.is_open()) {
+ // Cancel all outstanding operations and close the socket.
+ // Use the non-throwing variants and ignore errors, if any.
+ boost::system::error_code error;
+ m_socket.cancel(error);
+ m_socket.close(error);
+ }
m_pcap.reset();
- fail("Face closed");
+ // Ensure that the Transport stays alive at least
+ // until all pending handlers are dispatched
+ getGlobalIoService().post([this] {
+ this->setState(TransportState::CLOSED);
+ });
}
void
-EthernetFace::pcapInit()
+EthernetTransport::pcapInit()
{
char errbuf[PCAP_ERRBUF_SIZE] = {};
m_pcap.reset(pcap_create(m_interfaceName.c_str(), errbuf));
@@ -187,7 +181,7 @@
}
void
-EthernetFace::setPacketFilter(const char* filterString)
+EthernetTransport::setPacketFilter(const char* filterString)
{
bpf_program filter;
if (pcap_compile(m_pcap.get(), &filter, filterString, 1, PCAP_NETMASK_UNKNOWN) < 0)
@@ -200,14 +194,14 @@
}
bool
-EthernetFace::joinMulticastGroup()
+EthernetTransport::joinMulticastGroup()
{
#if defined(__linux__)
packet_mreq mr{};
mr.mr_ifindex = m_interfaceIndex;
mr.mr_type = PACKET_MR_MULTICAST;
mr.mr_alen = m_destAddress.size();
- std::copy(m_destAddress.begin(), m_destAddress.end(), mr.mr_address);
+ std::memcpy(mr.mr_address, m_destAddress.data(), m_destAddress.size());
if (::setsockopt(m_socket.native_handle(), SOL_PACKET,
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == 0)
@@ -223,7 +217,7 @@
#if defined(__APPLE__) || defined(__FreeBSD__)
// see bug #2327
using boost::asio::ip::udp;
- udp::socket sock(ref(getGlobalIoService()), udp::v4());
+ udp::socket sock(getGlobalIoService(), udp::v4());
int fd = sock.native_handle();
/*
@@ -242,7 +236,7 @@
sdl->sdl_len = sizeof(ifr.ifr_addr);
sdl->sdl_family = AF_LINK;
sdl->sdl_alen = m_destAddress.size();
- std::copy(m_destAddress.begin(), m_destAddress.end(), LLADDR(sdl));
+ std::memcpy(LLADDR(sdl), m_destAddress.data(), m_destAddress.size());
static_assert(sizeof(ifr.ifr_addr) >= offsetof(sockaddr_dl, sdl_data) + ethernet::ADDR_LEN,
"ifr_addr in struct ifreq is too small on this platform");
@@ -250,9 +244,9 @@
int fd = m_socket.native_handle();
ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
- std::copy(m_destAddress.begin(), m_destAddress.end(), ifr.ifr_hwaddr.sa_data);
+ std::memcpy(ifr.ifr_hwaddr.sa_data, m_destAddress.data(), m_destAddress.size());
- static_assert(sizeof(ifr.ifr_hwaddr) >= offsetof(sockaddr, sa_data) + ethernet::ADDR_LEN,
+ static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= ethernet::ADDR_LEN,
"ifr_hwaddr in struct ifreq is too small on this platform");
#endif
@@ -266,26 +260,17 @@
}
void
-EthernetFace::sendPacket(const ndn::Block& block)
+EthernetTransport::sendPacket(const ndn::Block& block)
{
- if (!m_pcap)
- {
- NFD_LOG_FACE_WARN("Trying to send on closed face");
- return fail("Face closed");
- }
-
- BOOST_ASSERT(block.size() <= m_interfaceMtu);
-
/// \todo Right now there is no reserve when packet is received, but
/// we should reserve some space at the beginning and at the end
ndn::EncodingBuffer buffer(block);
// pad with zeroes if the payload is too short
- if (block.size() < ethernet::MIN_DATA_LEN)
- {
- static const uint8_t padding[ethernet::MIN_DATA_LEN] = {};
- buffer.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
- }
+ if (block.size() < ethernet::MIN_DATA_LEN) {
+ static const uint8_t padding[ethernet::MIN_DATA_LEN] = {};
+ buffer.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
+ }
// construct and prepend the ethernet header
static uint16_t ethertype = htons(ethernet::ETHERTYPE_NDN);
@@ -296,66 +281,53 @@
// send the packet
int sent = pcap_inject(m_pcap.get(), buffer.buf(), buffer.size());
if (sent < 0)
- {
- return fail("pcap_inject: " + std::string(pcap_geterr(m_pcap.get())));
- }
+ NFD_LOG_FACE_ERROR("pcap_inject failed: " << pcap_geterr(m_pcap.get()));
else if (static_cast<size_t>(sent) < buffer.size())
- {
- return fail("Failed to inject frame");
- }
-
- NFD_LOG_FACE_TRACE("Successfully sent: " << block.size() << " bytes");
- this->getMutableCounters().getNOutBytes() += block.size();
+ NFD_LOG_FACE_ERROR("Failed to send the full frame: bufsize=" << buffer.size() << " sent=" << sent);
+ else
+ // print block size because we don't want to count the padding in buffer
+ NFD_LOG_FACE_TRACE("Successfully sent: " << block.size() << " bytes");
}
void
-EthernetFace::handleRead(const boost::system::error_code& error, size_t)
+EthernetTransport::handleRead(const boost::system::error_code& error, size_t)
{
- if (!m_pcap)
- return fail("Face closed");
-
if (error)
return processErrorCode(error);
pcap_pkthdr* header;
const uint8_t* packet;
+
+ // read the pcap header and packet data
int ret = pcap_next_ex(m_pcap.get(), &header, &packet);
if (ret < 0)
- {
- return fail("pcap_next_ex: " + std::string(pcap_geterr(m_pcap.get())));
- }
+ NFD_LOG_FACE_ERROR("pcap_next_ex failed: " << pcap_geterr(m_pcap.get()));
else if (ret == 0)
- {
- NFD_LOG_FACE_WARN("Read timeout");
- }
+ NFD_LOG_FACE_WARN("Read timeout");
else
- {
- processIncomingPacket(header, packet);
- }
+ processIncomingPacket(header, packet);
#ifdef _DEBUG
pcap_stat ps{};
ret = pcap_stats(m_pcap.get(), &ps);
- if (ret < 0)
- {
- NFD_LOG_FACE_DEBUG("pcap_stats failed: " << pcap_geterr(m_pcap.get()));
- }
- else if (ret == 0)
- {
- if (ps.ps_drop - m_nDropped > 0)
- NFD_LOG_FACE_DEBUG("Detected " << ps.ps_drop - m_nDropped << " dropped packet(s)");
- m_nDropped = ps.ps_drop;
- }
+ if (ret < 0) {
+ NFD_LOG_FACE_DEBUG("pcap_stats failed: " << pcap_geterr(m_pcap.get()));
+ }
+ else if (ret == 0) {
+ if (ps.ps_drop - m_nDropped > 0)
+ NFD_LOG_FACE_DEBUG("Detected " << ps.ps_drop - m_nDropped << " dropped packet(s)");
+ m_nDropped = ps.ps_drop;
+ }
#endif
m_socket.async_read_some(boost::asio::null_buffers(),
- bind(&EthernetFace::handleRead, this,
+ bind(&EthernetTransport::handleRead, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void
-EthernetFace::processIncomingPacket(const pcap_pkthdr* header, const uint8_t* packet)
+EthernetTransport::processIncomingPacket(const pcap_pkthdr* header, const uint8_t* packet)
{
size_t length = header->caplen;
if (length < ethernet::HDR_LEN + ethernet::MIN_DATA_LEN) {
@@ -377,77 +349,46 @@
packet += ethernet::HDR_LEN;
length -= ethernet::HDR_LEN;
- /// \todo Reserve space in front and at the back of the underlying buffer
bool isOk = false;
- Block fragmentBlock;
- std::tie(isOk, fragmentBlock) = Block::fromBuffer(packet, length);
+ Block element;
+ std::tie(isOk, element) = Block::fromBuffer(packet, length);
if (!isOk) {
- NFD_LOG_FACE_WARN("Block received from " << sourceAddress.toString()
- << " is invalid or too large to process");
+ NFD_LOG_FACE_WARN("Received invalid packet from " << sourceAddress.toString());
return;
}
- NFD_LOG_FACE_TRACE("Received: " << fragmentBlock.size() << " bytes from "
- << sourceAddress.toString());
- this->getMutableCounters().getNInBytes() += fragmentBlock.size();
+ NFD_LOG_FACE_TRACE("Received: " << element.size() << " bytes from " << sourceAddress.toString());
- Reassembler& reassembler = m_reassemblers[sourceAddress];
- if (!reassembler.pms) {
- // new sender, setup a PartialMessageStore for it
- reassembler.pms.reset(new ndnlp::PartialMessageStore);
- reassembler.pms->onReceive.connect(
- [this, sourceAddress] (const Block& block) {
- NFD_LOG_FACE_TRACE("All fragments received from " << sourceAddress.toString());
- if (!decodeAndDispatchInput(block))
- NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << block.type()
- << " from " << sourceAddress.toString());
- });
- }
-
- scheduler::cancel(reassembler.expireEvent);
- reassembler.expireEvent = scheduler::schedule(REASSEMBLER_LIFETIME,
- [this, sourceAddress] {
- BOOST_VERIFY(m_reassemblers.erase(sourceAddress) == 1);
- });
-
- ndnlp::NdnlpData fragment;
- std::tie(isOk, fragment) = ndnlp::NdnlpData::fromBlock(fragmentBlock);
- if (!isOk) {
- NFD_LOG_FACE_WARN("Received invalid NDNLP fragment from " << sourceAddress.toString());
- return;
- }
-
- reassembler.pms->receive(fragment);
+ Transport::Packet tp(std::move(element));
+ static_assert(sizeof(tp.remoteEndpoint) >= ethernet::ADDR_LEN,
+ "Transport::Packet::remoteEndpoint is too small");
+ std::memcpy(&tp.remoteEndpoint, sourceAddress.data(), sourceAddress.size());
+ this->receive(std::move(tp));
}
void
-EthernetFace::processErrorCode(const boost::system::error_code& error)
+EthernetTransport::processErrorCode(const boost::system::error_code& error)
{
- if (error == boost::asio::error::operation_aborted)
- // cancel() has been called on the socket
+ NFD_LOG_FACE_TRACE(__func__);
+
+ if (getState() == TransportState::CLOSING ||
+ getState() == TransportState::FAILED ||
+ getState() == TransportState::CLOSED ||
+ error == boost::asio::error::operation_aborted)
+ // transport is shutting down, ignore any errors
return;
- std::string msg;
- if (error == boost::asio::error::eof)
- {
- msg = "Face closed";
- }
- else
- {
- msg = "Receive operation failed: " + error.message();
- NFD_LOG_FACE_WARN(msg);
- }
- fail(msg);
+ NFD_LOG_FACE_WARN("Receive operation failed: " << error.message());
}
size_t
-EthernetFace::getInterfaceMtu()
+EthernetTransport::getInterfaceMtu()
{
#ifdef SIOCGIFMTU
#if defined(__APPLE__) || defined(__FreeBSD__)
// see bug #2328
using boost::asio::ip::udp;
- udp::socket sock(ref(getGlobalIoService()), udp::v4());
+ udp::socket sock(getGlobalIoService(), udp::v4());
int fd = sock.native_handle();
#else
int fd = m_socket.native_handle();
@@ -456,13 +397,17 @@
ifreq ifr{};
std::strncpy(ifr.ifr_name, m_interfaceName.c_str(), sizeof(ifr.ifr_name) - 1);
- if (::ioctl(fd, SIOCGIFMTU, &ifr) == 0)
+ if (::ioctl(fd, SIOCGIFMTU, &ifr) == 0) {
+ NFD_LOG_FACE_DEBUG("Interface MTU is " << ifr.ifr_mtu);
return static_cast<size_t>(ifr.ifr_mtu);
+ }
NFD_LOG_FACE_WARN("Failed to get interface MTU: " << std::strerror(errno));
#endif
+ NFD_LOG_FACE_DEBUG("Assuming default MTU of " << ethernet::MAX_DATA_LEN);
return ethernet::MAX_DATA_LEN;
}
+} // namespace face
} // namespace nfd
diff --git a/daemon/face/ethernet-face.hpp b/daemon/face/ethernet-transport.hpp
similarity index 71%
rename from daemon/face/ethernet-face.hpp
rename to daemon/face/ethernet-transport.hpp
index 2bbd781..1d41008 100644
--- a/daemon/face/ethernet-face.hpp
+++ b/daemon/face/ethernet-transport.hpp
@@ -23,17 +23,13 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NFD_DAEMON_FACE_ETHERNET_FACE_HPP
-#define NFD_DAEMON_FACE_ETHERNET_FACE_HPP
+#ifndef NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
+#define NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
#include "common.hpp"
-#include "face.hpp"
-#include "ndnlp-partial-message-store.hpp"
-#include "ndnlp-slicer.hpp"
+#include "transport.hpp"
#include "core/network-interface.hpp"
-#include <unordered_map>
-
#ifndef HAVE_LIBPCAP
#error "Cannot include this file when libpcap is not available"
#endif
@@ -44,43 +40,41 @@
struct pcap_pkthdr;
namespace nfd {
+namespace face {
/**
- * @brief Implementation of Face abstraction that uses raw
- * Ethernet frames as underlying transport mechanism
+ * \brief A multicast Transport that uses raw Ethernet II frames
*/
-class EthernetFace : public Face
+class EthernetTransport DECL_CLASS_FINAL : public Transport
{
public:
- /**
- * @brief EthernetFace-related error
- */
- struct Error : public Face::Error
+ class Error : public std::runtime_error
{
- Error(const std::string& what) : Face::Error(what) {}
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
};
- EthernetFace(boost::asio::posix::stream_descriptor socket,
- const NetworkInterfaceInfo& interface,
- const ethernet::Address& address);
-
- /// send an Interest
- void
- sendInterest(const Interest& interest) DECL_OVERRIDE;
-
- /// send a Data
- void
- sendData(const Data& data) DECL_OVERRIDE;
-
/**
- * @brief Closes the face
- *
- * This terminates all communication on the face and triggers the onFail() event.
+ * @brief Creates an Ethernet-based transport for multicast communication
*/
- void
- close() DECL_OVERRIDE;
+ EthernetTransport(const NetworkInterfaceInfo& interface,
+ const ethernet::Address& mcastAddress);
+
+protected:
+ virtual void
+ beforeChangePersistency(ndn::nfd::FacePersistency newPersistency) DECL_FINAL;
+
+ virtual void
+ doClose() DECL_FINAL;
private:
+ virtual void
+ doSend(Transport::Packet&& packet) DECL_FINAL;
+
/**
* @brief Allocates and initializes a libpcap context for live capture
*/
@@ -139,26 +133,15 @@
getInterfaceMtu();
private:
- struct Reassembler
- {
- unique_ptr<ndnlp::PartialMessageStore> pms;
- scheduler::EventId expireEvent;
- };
-
unique_ptr<pcap_t, void(*)(pcap_t*)> m_pcap;
boost::asio::posix::stream_descriptor m_socket;
+ ethernet::Address m_srcAddress;
+ ethernet::Address m_destAddress;
+ std::string m_interfaceName;
#if defined(__linux__)
int m_interfaceIndex;
#endif
- std::string m_interfaceName;
- ethernet::Address m_srcAddress;
- ethernet::Address m_destAddress;
-
- size_t m_interfaceMtu;
- unique_ptr<ndnlp::Slicer> m_slicer;
- std::unordered_map<ethernet::Address, Reassembler> m_reassemblers;
- static const time::nanoseconds REASSEMBLER_LIFETIME;
#ifdef _DEBUG
/// number of packets dropped by the kernel, as reported by libpcap
@@ -166,6 +149,7 @@
#endif
};
+} // namespace face
} // namespace nfd
-#endif // NFD_DAEMON_FACE_ETHERNET_FACE_HPP
+#endif // NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
diff --git a/daemon/face/ndnlp-data.cpp b/daemon/face/ndnlp-data.cpp
deleted file mode 100644
index 7cfacac..0000000
--- a/daemon/face/ndnlp-data.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- 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 "ndnlp-data.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-std::tuple<bool, NdnlpData>
-NdnlpData::fromBlock(const Block& wire)
-{
- if (wire.type() != tlv::NdnlpData) {
- // top element is not NdnlpData
- return std::make_tuple(false, NdnlpData());
- }
- wire.parse();
- const Block::element_container& elements = wire.elements();
- if (elements.size() < 2) {
- // NdnlpData element has incorrect number of children
- return std::make_tuple(false, NdnlpData());
- }
-
- NdnlpData parsed;
-
- const Block& sequenceElement = elements.front();
- if (sequenceElement.type() != tlv::NdnlpSequence) {
- // NdnlpSequence element is missing
- return std::make_tuple(false, NdnlpData());
- }
- if (sequenceElement.value_size() != sizeof(uint64_t)) {
- // NdnlpSequence element has incorrect length
- return std::make_tuple(false, NdnlpData());
- }
- parsed.seq = be64toh(*reinterpret_cast<const uint64_t*>(&*sequenceElement.value_begin()));
-
- const Block& payloadElement = elements.back();
- if (payloadElement.type() != tlv::NdnlpPayload) {
- // NdnlpPayload element is missing
- return std::make_tuple(false, NdnlpData());
- }
- parsed.payload = payloadElement;
-
- if (elements.size() == 2) { // single wire packet
- parsed.fragIndex = 0;
- parsed.fragCount = 1;
- return std::make_tuple(true, parsed);
- }
- if (elements.size() != 4) {
- // NdnlpData element has incorrect number of children
- return std::make_tuple(false, NdnlpData());
- }
-
- const Block& fragIndexElement = elements.at(1);
- if (fragIndexElement.type() != tlv::NdnlpFragIndex) {
- // NdnlpFragIndex element is missing
- return std::make_tuple(false, NdnlpData());
- }
- uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
- if (fragIndex > std::numeric_limits<uint16_t>::max()) {
- // NdnlpFragIndex is too large
- return std::make_tuple(false, NdnlpData());
- }
- parsed.fragIndex = static_cast<uint16_t>(fragIndex);
-
- const Block& fragCountElement = elements.at(2);
- if (fragCountElement.type() != tlv::NdnlpFragCount) {
- // NdnlpFragCount element is missing
- return std::make_tuple(false, NdnlpData());
- }
- uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
- if (fragCount > std::numeric_limits<uint16_t>::max()) {
- // NdnlpFragCount is too large
- return std::make_tuple(false, NdnlpData());
- }
- parsed.fragCount = static_cast<uint16_t>(fragCount);
-
- if (parsed.fragIndex >= parsed.fragCount) {
- // NdnlpFragIndex must be less than NdnlpFragCount
- return std::make_tuple(false, NdnlpData());
- }
-
- return std::make_tuple(true, parsed);
-}
-
-} // namespace ndnlp
-} // namespace nfd
diff --git a/daemon/face/ndnlp-data.hpp b/daemon/face/ndnlp-data.hpp
deleted file mode 100644
index fd921e2..0000000
--- a/daemon/face/ndnlp-data.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- 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_FACE_NDNLP_PARSE_HPP
-#define NFD_DAEMON_FACE_NDNLP_PARSE_HPP
-
-#include "common.hpp"
-#include "ndnlp-tlv.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-/** \brief represents a NdnlpData packet
- *
- * NdnlpData ::= NDNLP-DATA-TYPE TLV-LENGTH
- * NdnlpSequence
- * NdnlpFragIndex?
- * NdnlpFragCount?
- * NdnlpPayload
- */
-class NdnlpData
-{
-public:
- /** \brief parse a NdnlpData packet
- * \return whether \p wire has a valid NdnlpData packet, and the parsed packet
- */
- static std::tuple<bool, NdnlpData>
- fromBlock(const Block& wire);
-
-public:
- uint64_t seq;
- uint16_t fragIndex;
- uint16_t fragCount;
- Block payload;
-};
-
-} // namespace ndnlp
-} // namespace nfd
-
-#endif // NFD_DAEMON_FACE_NDNLP_PARSE_HPP
diff --git a/daemon/face/ndnlp-partial-message-store.cpp b/daemon/face/ndnlp-partial-message-store.cpp
deleted file mode 100644
index 252e77d..0000000
--- a/daemon/face/ndnlp-partial-message-store.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/* -*- 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 "ndnlp-partial-message-store.hpp"
-#include "core/logger.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-NFD_LOG_INIT("NdnlpPartialMessageStore");
-
-PartialMessage::PartialMessage()
- : m_fragCount(0)
- , m_received(0)
- , m_totalLength(0)
-{
-}
-
-bool
-PartialMessage::add(uint16_t fragIndex, uint16_t fragCount, const Block& payload)
-{
- if (m_received == 0) { // first packet
- m_fragCount = fragCount;
- m_payloads.resize(fragCount);
- }
-
- if (m_fragCount != fragCount || fragIndex >= m_fragCount) {
- return false;
- }
-
- if (!m_payloads[fragIndex].empty()) { // duplicate
- return false;
- }
-
- m_payloads[fragIndex] = payload;
- ++m_received;
- m_totalLength += payload.value_size();
- return true;
-}
-
-bool
-PartialMessage::isComplete() const
-{
- return m_received == m_fragCount;
-}
-
-std::tuple<bool, Block>
-PartialMessage::reassemble()
-{
- BOOST_ASSERT(this->isComplete());
-
- ndn::BufferPtr buffer = make_shared<ndn::Buffer>(m_totalLength);
- ndn::Buffer::iterator buf = buffer->begin();
- for (const Block& payload : m_payloads) {
- buf = std::copy(payload.value_begin(), payload.value_end(), buf);
- }
- BOOST_ASSERT(buf == buffer->end());
-
- return Block::fromBuffer(buffer, 0);
-}
-
-std::tuple<bool, Block>
-PartialMessage::reassembleSingle(const NdnlpData& fragment)
-{
- BOOST_ASSERT(fragment.fragCount == 1);
-
- try {
- return std::make_tuple(true, fragment.payload.blockFromValue());
- }
- catch (tlv::Error&) {
- return std::make_tuple(false, Block());
- }
-}
-
-PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration)
- : m_idleDuration(idleDuration)
-{
-}
-
-void
-PartialMessageStore::receive(const NdnlpData& pkt)
-{
- bool isReassembled = false;
- Block reassembled;
-
- if (pkt.fragCount == 1) { // single fragment
- std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt);
- }
- else {
- uint64_t messageIdentifier = pkt.seq - pkt.fragIndex;
- PartialMessage& pm = m_partialMessages[messageIdentifier];
- this->scheduleCleanup(messageIdentifier, pm);
-
- pm.add(pkt.fragIndex, pkt.fragCount, pkt.payload);
-
- if (pm.isComplete()) {
- std::tie(isReassembled, reassembled) = pm.reassemble();
- m_partialMessages.erase(messageIdentifier);
- }
- else {
- return;
- }
- }
-
- if (!isReassembled) {
- NFD_LOG_TRACE(pkt.seq << " reassemble error");
- return;
- }
-
- NFD_LOG_TRACE(pkt.seq << " deliver");
- this->onReceive(reassembled);
-}
-
-void
-PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier,
- PartialMessage& partialMessage)
-{
- partialMessage.expiry = scheduler::schedule(m_idleDuration,
- bind(&PartialMessageStore::cleanup, this, messageIdentifier));
-}
-
-void
-PartialMessageStore::cleanup(uint64_t messageIdentifier)
-{
- NFD_LOG_TRACE(messageIdentifier << " cleanup");
- m_partialMessages.erase(messageIdentifier);
-}
-
-} // namespace ndnlp
-} // namespace nfd
diff --git a/daemon/face/ndnlp-partial-message-store.hpp b/daemon/face/ndnlp-partial-message-store.hpp
deleted file mode 100644
index 25afcd8..0000000
--- a/daemon/face/ndnlp-partial-message-store.hpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- 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_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
-#define NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
-
-#include "ndnlp-data.hpp"
-#include "core/scheduler.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-/** \brief represents a partially received message
- */
-class PartialMessage
-{
-public:
- PartialMessage();
-
- PartialMessage(const PartialMessage&) = delete;
-
- PartialMessage&
- operator=(const PartialMessage&) = delete;
-
- PartialMessage(PartialMessage&&) = default;
-
- PartialMessage&
- operator=(PartialMessage&&) = default;
-
- bool
- add(uint16_t fragIndex, uint16_t fragCount, const Block& payload);
-
- bool
- isComplete() const;
-
- /** \brief reassemble network layer packet
- * \pre isComplete() == true
- * \return whether success, network layer packet
- */
- std::tuple<bool, Block>
- reassemble();
-
- /** \brief reassemble network layer packet from a single fragment
- * \pre fragment.fragCount == 1
- * \return whether success, network layer packet
- */
- static std::tuple<bool, Block>
- reassembleSingle(const NdnlpData& fragment);
-
-public:
- scheduler::ScopedEventId expiry;
-
-private:
- size_t m_fragCount;
- size_t m_received;
- std::vector<Block> m_payloads;
- size_t m_totalLength;
-};
-
-/** \brief provides reassembly feature at receiver
- */
-class PartialMessageStore : noncopyable
-{
-public:
- explicit
- PartialMessageStore(const time::nanoseconds& idleDuration = time::milliseconds(100));
-
- /** \brief receive a NdnlpData packet
- *
- * Reassembly errors will be ignored.
- */
- void
- receive(const NdnlpData& pkt);
-
- /** \brief fires when network layer packet is received
- */
- signal::Signal<PartialMessageStore, Block> onReceive;
-
-private:
- void
- scheduleCleanup(uint64_t messageIdentifier, PartialMessage& partialMessage);
-
- void
- cleanup(uint64_t messageIdentifier);
-
-private:
- std::unordered_map<uint64_t, PartialMessage> m_partialMessages;
-
- time::nanoseconds m_idleDuration;
-};
-
-} // namespace ndnlp
-} // namespace nfd
-
-#endif // NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
diff --git a/daemon/face/ndnlp-sequence-generator.cpp b/daemon/face/ndnlp-sequence-generator.cpp
deleted file mode 100644
index 842a319..0000000
--- a/daemon/face/ndnlp-sequence-generator.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- 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
- *
- * 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 "ndnlp-sequence-generator.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-SequenceBlock::SequenceBlock(uint64_t start, size_t count)
- : m_start(start)
- , m_count(count)
-{
-}
-
-SequenceGenerator::SequenceGenerator()
- : m_next(0)
-{
-}
-
-SequenceBlock
-SequenceGenerator::nextBlock(size_t count)
-{
- SequenceBlock sb(m_next, count);
- m_next += count;
- return sb;
-}
-
-} // namespace ndnlp
-} // namespace nfd
diff --git a/daemon/face/ndnlp-sequence-generator.hpp b/daemon/face/ndnlp-sequence-generator.hpp
deleted file mode 100644
index 3019933..0000000
--- a/daemon/face/ndnlp-sequence-generator.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- 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
- *
- * 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_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
-#define NFD_DAEMON_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
-
-#include "common.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-/** \brief represents a block of sequence numbers
- */
-class SequenceBlock
-{
-public:
- SequenceBlock(uint64_t start, size_t count);
-
- /** \return{ the pos-th sequence number }
- */
- uint64_t
- operator[](size_t pos) const;
-
- size_t
- count() const;
-
-private:
- uint64_t m_start;
- size_t m_count;
-};
-
-inline uint64_t
-SequenceBlock::operator[](size_t pos) const
-{
- if (pos >= m_count)
- BOOST_THROW_EXCEPTION(std::out_of_range("pos"));
- return m_start + static_cast<uint64_t>(pos);
-}
-
-inline size_t
-SequenceBlock::count() const
-{
- return m_count;
-}
-
-/** \class SequenceGenerator
- * \brief generates sequence numbers
- */
-class SequenceGenerator : noncopyable
-{
-public:
- SequenceGenerator();
-
- /** \brief generates a block of consecutive sequence numbers
- *
- * This block must not overlap with a recent block.
- */
- SequenceBlock
- nextBlock(size_t count);
-
-private:
- /// next sequence number
- uint64_t m_next;
-};
-
-} // namespace ndnlp
-} // namespace nfd
-
-#endif // NFD_DAEMON_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
diff --git a/daemon/face/ndnlp-slicer.cpp b/daemon/face/ndnlp-slicer.cpp
deleted file mode 100644
index 03b1454..0000000
--- a/daemon/face/ndnlp-slicer.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- 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 "ndnlp-slicer.hpp"
-
-#include <ndn-cxx/encoding/encoding-buffer.hpp>
-
-namespace nfd {
-namespace ndnlp {
-
-Slicer::Slicer(size_t mtu)
- : m_mtu(mtu)
-{
- this->estimateOverhead();
-}
-
-Slicer::~Slicer()
-{
-}
-
-template<bool T>
-size_t
-Slicer::encodeFragment(ndn::EncodingImpl<T>& blk,
- uint64_t seq, uint16_t fragIndex, uint16_t fragCount,
- const uint8_t* payload, size_t payloadSize)
-{
- size_t totalLength = 0;
-
- // NdnlpPayload
- size_t payloadLength = blk.prependByteArray(payload, payloadSize);
- totalLength += payloadLength;
- totalLength += blk.prependVarNumber(payloadLength);
- totalLength += blk.prependVarNumber(tlv::NdnlpPayload);
-
- bool needFragIndexAndCount = fragCount > 1;
- if (needFragIndexAndCount) {
- // NdnlpFragCount
- size_t fragCountLength = blk.prependNonNegativeInteger(fragCount);
- totalLength += fragCountLength;
- totalLength += blk.prependVarNumber(fragCountLength);
- totalLength += blk.prependVarNumber(tlv::NdnlpFragCount);
-
- // NdnlpFragIndex
- size_t fragIndexLength = blk.prependNonNegativeInteger(fragIndex);
- totalLength += fragIndexLength;
- totalLength += blk.prependVarNumber(fragIndexLength);
- totalLength += blk.prependVarNumber(tlv::NdnlpFragIndex);
- }
-
- // NdnlpSequence
- uint64_t sequenceBE = htobe64(seq);
- size_t sequenceLength = blk.prependByteArray(
- reinterpret_cast<uint8_t*>(&sequenceBE), sizeof(sequenceBE));
- totalLength += sequenceLength;
- totalLength += blk.prependVarNumber(sequenceLength);
- totalLength += blk.prependVarNumber(tlv::NdnlpSequence);
-
- // NdnlpData
- totalLength += blk.prependVarNumber(totalLength);
- totalLength += blk.prependVarNumber(tlv::NdnlpData);
-
- return totalLength;
-}
-
-void
-Slicer::estimateOverhead()
-{
- // estimate fragment size with all header fields at largest possible size
- ndn::EncodingEstimator estimator;
- size_t estimatedSize = this->encodeFragment(estimator,
- std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint16_t>::max() - 1,
- std::numeric_limits<uint16_t>::max(),
- nullptr, m_mtu);
-
- size_t overhead = estimatedSize - m_mtu; // minus payload length in estimation
- m_maxPayload = m_mtu - overhead;
-}
-
-PacketArray
-Slicer::slice(const Block& block)
-{
- BOOST_ASSERT(block.hasWire());
- const uint8_t* networkPacket = block.wire();
- size_t networkPacketSize = block.size();
-
- uint16_t fragCount = static_cast<uint16_t>(
- (networkPacketSize / m_maxPayload) +
- (networkPacketSize % m_maxPayload == 0 ? 0 : 1)
- );
- PacketArray pa = make_shared<std::vector<Block>>();
- pa->reserve(fragCount);
- SequenceBlock seqBlock = m_seqgen.nextBlock(fragCount);
-
- for (uint16_t fragIndex = 0; fragIndex < fragCount; ++fragIndex) {
- size_t payloadOffset = fragIndex * m_maxPayload;
- const uint8_t* payload = networkPacket + payloadOffset;
- size_t payloadSize = std::min(m_maxPayload, networkPacketSize - payloadOffset);
-
- ndn::EncodingBuffer buffer(m_mtu, 0);
- size_t pktSize = this->encodeFragment(buffer,
- seqBlock[fragIndex], fragIndex, fragCount, payload, payloadSize);
-
- BOOST_VERIFY(pktSize <= m_mtu);
-
- pa->push_back(buffer.block());
- }
-
- return pa;
-}
-
-} // namespace ndnlp
-} // namespace nfd
diff --git a/daemon/face/ndnlp-slicer.hpp b/daemon/face/ndnlp-slicer.hpp
deleted file mode 100644
index 1e2985a..0000000
--- a/daemon/face/ndnlp-slicer.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- 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_FACE_NDNLP_SLICER_HPP
-#define NFD_DAEMON_FACE_NDNLP_SLICER_HPP
-
-#include "ndnlp-tlv.hpp"
-#include "ndnlp-sequence-generator.hpp"
-
-namespace nfd {
-namespace ndnlp {
-
-typedef shared_ptr<std::vector<Block>> PacketArray;
-
-/** \brief provides fragmentation feature at sender
- */
-class Slicer : noncopyable
-{
-public:
- /** \param mtu maximum size of NDNLP header and payload
- * \note If NDNLP packets are to be encapsulated in an additional header
- * (eg. in UDP packets), the caller must deduct such overhead.
- */
- explicit
- Slicer(size_t mtu);
-
- virtual
- ~Slicer();
-
- PacketArray
- slice(const Block& block);
-
-private:
- template<bool T>
- size_t
- encodeFragment(ndn::EncodingImpl<T>& blk,
- uint64_t seq, uint16_t fragIndex, uint16_t fragCount,
- const uint8_t* payload, size_t payloadSize);
-
- /// estimate the size of NDNLP header and maximum payload size per packet
- void
- estimateOverhead();
-
-private:
- SequenceGenerator m_seqgen;
-
- /// maximum packet size
- size_t m_mtu;
-
- /// maximum payload size
- size_t m_maxPayload;
-};
-
-} // namespace ndnlp
-} // namespace nfd
-
-#endif // NFD_DAEMON_FACE_NDNLP_SLICER_HPP
diff --git a/daemon/face/ndnlp-tlv.hpp b/daemon/face/ndnlp-tlv.hpp
deleted file mode 100644
index 0c41f52..0000000
--- a/daemon/face/ndnlp-tlv.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- 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
- *
- * 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_FACE_NDNLP_TLV_HPP
-#define NFD_DAEMON_FACE_NDNLP_TLV_HPP
-
-namespace nfd {
-namespace tlv {
-
-enum
-{
- NdnlpData = 80,
- NdnlpSequence = 81,
- NdnlpFragIndex = 82,
- NdnlpFragCount = 83,
- NdnlpPayload = 84
-};
-
-} // namespace tlv
-} // namespace nfd
-
-#endif // NFD_DAEMON_FACE_NDNLP_TLV_HPP
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 1b68a3d..1bc1701 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -42,7 +42,7 @@
#ifdef HAVE_LIBPCAP
#include "face/ethernet-factory.hpp"
-#include "face/ethernet-face.hpp"
+#include "face/ethernet-transport.hpp"
#endif // HAVE_LIBPCAP
#ifdef HAVE_WEBSOCKET
@@ -806,7 +806,7 @@
m_factories.insert(std::make_pair("ether", factory));
}
- std::set<shared_ptr<EthernetFace>> multicastFacesToRemove;
+ std::set<shared_ptr<face::LpFaceWrapper>> multicastFacesToRemove;
for (const auto& i : factory->getMulticastFaces()) {
multicastFacesToRemove.insert(i.second);
}
@@ -822,7 +822,7 @@
catch (const EthernetFactory::Error& factoryError) {
NFD_LOG_ERROR(factoryError.what() << ", continuing");
}
- catch (const EthernetFace::Error& faceError) {
+ catch (const face::EthernetTransport::Error& faceError) {
NFD_LOG_ERROR(faceError.what() << ", continuing");
}
}
diff --git a/tests/daemon/face/ethernet-transport.t.cpp b/tests/daemon/face/ethernet-transport.t.cpp
new file mode 100644
index 0000000..85c799d
--- /dev/null
+++ b/tests/daemon/face/ethernet-transport.t.cpp
@@ -0,0 +1,60 @@
+/* -*- 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 "face/ethernet-transport.hpp"
+#include "transport-properties.hpp"
+
+#include "network-interface-fixture.hpp"
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+using namespace nfd::tests;
+
+BOOST_AUTO_TEST_SUITE(Face)
+BOOST_FIXTURE_TEST_SUITE(TestEthernetTransport, NetworkInterfaceFixture)
+
+BOOST_AUTO_TEST_CASE(StaticProperties)
+{
+ SKIP_IF_NETWORK_INTERFACE_COUNT_LT(1);
+
+ auto netif = m_interfaces.front();
+ EthernetTransport transport(netif, ethernet::getDefaultMulticastAddress());
+ checkStaticPropertiesInitialized(transport);
+
+ BOOST_CHECK_EQUAL(transport.getLocalUri(), FaceUri::fromDev(netif.name));
+ BOOST_CHECK_EQUAL(transport.getRemoteUri(), FaceUri(ethernet::getDefaultMulticastAddress()));
+ BOOST_CHECK_EQUAL(transport.getScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
+ BOOST_CHECK_EQUAL(transport.getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
+ BOOST_CHECK_EQUAL(transport.getLinkType(), ndn::nfd::LINK_TYPE_MULTI_ACCESS);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestEthernetTransport
+BOOST_AUTO_TEST_SUITE_END() // Face
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
diff --git a/tests/daemon/face/ethernet.t.cpp b/tests/daemon/face/ethernet.t.cpp
index 7d97016..0098436 100644
--- a/tests/daemon/face/ethernet.t.cpp
+++ b/tests/daemon/face/ethernet.t.cpp
@@ -23,11 +23,11 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "face/ethernet-face.hpp"
#include "face/ethernet-factory.hpp"
+#include "face/ethernet-transport.hpp"
-#include "core/network-interface.hpp"
-#include "tests/test-common.hpp"
+#include "face/lp-face-wrapper.hpp"
+#include "network-interface-fixture.hpp"
#include <pcap/pcap.h>
@@ -35,36 +35,10 @@
namespace tests {
BOOST_AUTO_TEST_SUITE(Face)
+BOOST_FIXTURE_TEST_SUITE(TestEthernet, NetworkInterfaceFixture)
using nfd::Face;
-class InterfacesFixture : protected BaseFixture
-{
-protected:
- InterfacesFixture()
- {
- EthernetFactory factory;
-
- for (const auto& netif : listNetworkInterfaces()) {
- if (!netif.isLoopback() && netif.isUp()) {
- try {
- factory.createMulticastFace(netif, ethernet::getBroadcastAddress());
- }
- catch (Face::Error&) {
- continue;
- }
-
- m_interfaces.push_back(netif);
- }
- }
- }
-
-protected:
- std::vector<NetworkInterfaceInfo> m_interfaces;
-};
-
-BOOST_FIXTURE_TEST_SUITE(TestEthernet, InterfacesFixture)
-
BOOST_AUTO_TEST_CASE(GetChannels)
{
EthernetFactory factory;
@@ -75,31 +49,19 @@
BOOST_AUTO_TEST_CASE(MulticastFacesMap)
{
- if (m_interfaces.empty()) {
- BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
- "cannot perform MulticastFacesMap test");
- return;
- }
+ SKIP_IF_NETWORK_INTERFACE_COUNT_LT(1);
EthernetFactory factory;
- shared_ptr<EthernetFace> face1 = factory.createMulticastFace(m_interfaces.front(),
- ethernet::getBroadcastAddress());
- shared_ptr<EthernetFace> face1bis = factory.createMulticastFace(m_interfaces.front(),
- ethernet::getBroadcastAddress());
+ auto face1 = factory.createMulticastFace(m_interfaces.front(), ethernet::getBroadcastAddress());
+ auto face1bis = factory.createMulticastFace(m_interfaces.front(), ethernet::getBroadcastAddress());
BOOST_CHECK_EQUAL(face1, face1bis);
- if (m_interfaces.size() > 1) {
- shared_ptr<EthernetFace> face2 = factory.createMulticastFace(m_interfaces.back(),
- ethernet::getBroadcastAddress());
- BOOST_CHECK_NE(face1, face2);
- }
- else {
- BOOST_WARN_MESSAGE(false, "Only one interface available for pcap, "
- "cannot test second EthernetFace creation");
- }
+ auto face2 = factory.createMulticastFace(m_interfaces.front(), ethernet::getDefaultMulticastAddress());
+ BOOST_CHECK_NE(face1, face2);
- shared_ptr<EthernetFace> face3 = factory.createMulticastFace(m_interfaces.front(),
- ethernet::getDefaultMulticastAddress());
+ SKIP_IF_NETWORK_INTERFACE_COUNT_LT(2);
+
+ auto face3 = factory.createMulticastFace(m_interfaces.back(), ethernet::getBroadcastAddress());
BOOST_CHECK_NE(face1, face3);
}
@@ -128,19 +90,14 @@
BOOST_AUTO_TEST_CASE(SendPacket)
{
- if (m_interfaces.empty()) {
- BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
- "cannot perform SendPacket test");
- return;
- }
+ SKIP_IF_NETWORK_INTERFACE_COUNT_LT(1);
EthernetFactory factory;
- shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
- ethernet::getDefaultMulticastAddress());
+ auto face = factory.createMulticastFace(m_interfaces.front(), ethernet::getDefaultMulticastAddress());
BOOST_REQUIRE(static_cast<bool>(face));
BOOST_CHECK_EQUAL(face->isLocal(), false);
- BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
+ BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
BOOST_CHECK_EQUAL(face->isMultiAccess(), true);
BOOST_CHECK_EQUAL(face->getRemoteUri().toString(),
"ether://[" + ethernet::getDefaultMulticastAddress().toString() + "]");
@@ -162,40 +119,23 @@
face->sendData (*data2 );
BOOST_CHECK_EQUAL(face->getCounters().nOutBytes,
- 14 * 4 + // 4 NDNLP headers
interest1->wireEncode().size() +
data1->wireEncode().size() +
interest2->wireEncode().size() +
data2->wireEncode().size());
-
-// m_ioRemaining = 4;
-// m_ioService.run();
-// m_ioService.reset();
-
-// BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
-// BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
-// BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
-// BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
-
-// BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
-// BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
-// BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
-// BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
}
BOOST_AUTO_TEST_CASE(ProcessIncomingPacket)
{
- if (m_interfaces.empty()) {
- BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
- "cannot perform ProcessIncomingPacket test");
- return;
- }
+ SKIP_IF_NETWORK_INTERFACE_COUNT_LT(1);
EthernetFactory factory;
- shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
- ethernet::getDefaultMulticastAddress());
+ auto face = factory.createMulticastFace(m_interfaces.front(), ethernet::getDefaultMulticastAddress());
BOOST_REQUIRE(static_cast<bool>(face));
+ auto transport = dynamic_cast<face::EthernetTransport*>(face->getLpFace()->getTransport());
+ BOOST_REQUIRE(transport != nullptr);
+
std::vector<Interest> recInterests;
std::vector<Data> recDatas;
@@ -206,7 +146,7 @@
// check that packet data is not accessed if pcap didn't capture anything (caplen == 0)
static const pcap_pkthdr zeroHeader{};
- face->processIncomingPacket(&zeroHeader, nullptr);
+ transport->processIncomingPacket(&zeroHeader, nullptr);
BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
BOOST_CHECK_EQUAL(recInterests.size(), 0);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
@@ -215,7 +155,7 @@
pcap_pkthdr runtHeader{};
runtHeader.caplen = ethernet::HDR_LEN + 6;
static const uint8_t packet2[ethernet::HDR_LEN + 6]{};
- face->processIncomingPacket(&runtHeader, packet2);
+ transport->processIncomingPacket(&runtHeader, packet2);
BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
BOOST_CHECK_EQUAL(recInterests.size(), 0);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
@@ -227,10 +167,10 @@
0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
0x86, 0x24, // NDN ethertype
- tlv::NdnlpData, // TLV type
+ tlv::Interest, // TLV type
0xfd, 0xff, 0xff // TLV length (invalid because greater than buffer size)
};
- face->processIncomingPacket(&validHeader, packet3);
+ transport->processIncomingPacket(&validHeader, packet3);
BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
BOOST_CHECK_EQUAL(recInterests.size(), 0);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
@@ -243,44 +183,41 @@
0x00, // TLV type (invalid)
0x00 // TLV length
};
- face->processIncomingPacket(&validHeader, packet4);
+ transport->processIncomingPacket(&validHeader, packet4);
BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 2);
BOOST_CHECK_EQUAL(recInterests.size(), 0);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
- // valid frame and valid NDNLP header, but invalid payload
+ // valid frame and valid NDNLPv2 packet, but invalid network-layer packet
static const uint8_t packet5[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
- 0x86, 0x24, // NDN ethertype
- tlv::NdnlpData, 0x0e, // NDNLP header
- tlv::NdnlpSequence, 0x08,
- 0, 0, 0, 0, 0, 0, 0, 0,
- tlv::NdnlpPayload, 0x02,
- 0x00, // NDN TLV type (invalid)
- 0x00 // NDN TLV length
+ 0x86, 0x24, // NDN ethertype
+ lp::tlv::LpPacket, 0x04, // start of NDNLPv2 packet
+ lp::tlv::Fragment, 0x02, // single fragment
+ 0x00, // TLV type (invalid)
+ 0x00 // TLV length
};
- face->processIncomingPacket(&validHeader, packet5);
- BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 18);
+ transport->processIncomingPacket(&validHeader, packet5);
+ BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 8);
BOOST_CHECK_EQUAL(recInterests.size(), 0);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
- // valid frame, valid NDNLP header, and valid NDN (interest) packet
+ // valid frame, valid NDNLPv2 packet, and valid NDN (interest) packet
static const uint8_t packet6[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
0x86, 0x24, // NDN ethertype
- tlv::NdnlpData, 0x24, // NDNLP TLV type and length
- 0x51, 0x08, 0x00, 0x00, 0x00, 0x00, // rest of NDNLP header
- 0x00, 0x00, 0x00, 0x00, 0x54, 0x18,
- tlv::Interest, 0x16, // NDN TLV type and length
+ lp::tlv::LpPacket, 0x1a, // start of NDNLPv2 packet
+ lp::tlv::Fragment, 0x18, // single fragment
+ tlv::Interest, 0x16, // start of NDN packet
0x07, 0x0e, 0x08, 0x07, 0x65, 0x78, // payload
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x08,
0x03, 0x66, 0x6f, 0x6f, 0x0a, 0x04,
0x03, 0xef, 0xe9, 0x7c
};
- face->processIncomingPacket(&validHeader, packet6);
- BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 56);
+ transport->processIncomingPacket(&validHeader, packet6);
+ BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 36);
BOOST_CHECK_EQUAL(recInterests.size(), 1);
BOOST_CHECK_EQUAL(recDatas.size(), 0);
}
diff --git a/tests/daemon/face/ndnlp.t.cpp b/tests/daemon/face/ndnlp.t.cpp
deleted file mode 100644
index b372769..0000000
--- a/tests/daemon/face/ndnlp.t.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*- 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 "face/ndnlp-sequence-generator.hpp"
-#include "face/ndnlp-slicer.hpp"
-#include "face/ndnlp-partial-message-store.hpp"
-
-#include "tests/test-common.hpp"
-
-#include <boost/scoped_array.hpp>
-
-namespace nfd {
-namespace ndnlp {
-namespace tests {
-
-using namespace nfd::tests;
-
-BOOST_FIXTURE_TEST_SUITE(FaceNdnlp, BaseFixture)
-
-BOOST_AUTO_TEST_CASE(SequenceBlock)
-{
- ndnlp::SequenceBlock sb(0x8000, 2);
- BOOST_CHECK_EQUAL(sb.count(), 2);
- BOOST_CHECK_EQUAL(sb[0], 0x8000);
- BOOST_CHECK_EQUAL(sb[1], 0x8001);
- BOOST_CHECK_THROW(sb[2], std::out_of_range);
-}
-
-// sequence number can safely wrap around
-BOOST_AUTO_TEST_CASE(SequenceBlockWrap)
-{
- ndnlp::SequenceBlock sb(std::numeric_limits<uint64_t>::max(), 2);
- BOOST_CHECK_EQUAL(sb[0], std::numeric_limits<uint64_t>::max());
- BOOST_CHECK_EQUAL(sb[1], std::numeric_limits<uint64_t>::min());
- BOOST_CHECK_EQUAL(sb[1] - sb[0], 1);
-}
-
-BOOST_AUTO_TEST_CASE(SequenceGenerator)
-{
- ndnlp::SequenceGenerator seqgen;
-
- ndnlp::SequenceBlock sb1 = seqgen.nextBlock(2);
- BOOST_CHECK_EQUAL(sb1.count(), 2);
-
- ndnlp::SequenceBlock sb2 = seqgen.nextBlock(1);
- BOOST_CHECK_NE(sb1[0], sb2[0]);
- BOOST_CHECK_NE(sb1[1], sb2[0]);
-}
-
-// slice a Block to one fragment
-BOOST_AUTO_TEST_CASE(Slice1)
-{
- uint8_t blockValue[60];
- memset(blockValue, 0xcc, sizeof(blockValue));
- Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
-
- ndnlp::Slicer slicer(9000);
- ndnlp::PacketArray pa = slicer.slice(block);
-
- BOOST_REQUIRE_EQUAL(pa->size(), 1);
-
- const Block& pkt = pa->at(0);
- BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
- pkt.parse();
-
- const Block::element_container& elements = pkt.elements();
- BOOST_REQUIRE_EQUAL(elements.size(), 2);
-
- const Block& sequenceElement = elements[0];
- BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
- BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));
-
- const Block& payloadElement = elements[1];
- BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
- size_t payloadSize = payloadElement.value_size();
- BOOST_CHECK_EQUAL(payloadSize, block.size());
-
- BOOST_CHECK_EQUAL_COLLECTIONS(payloadElement.value_begin(), payloadElement.value_end(),
- block.begin(), block.end());
-}
-
-// slice a Block to four fragments
-BOOST_AUTO_TEST_CASE(Slice4)
-{
- uint8_t blockValue[5050];
- memset(blockValue, 0xcc, sizeof(blockValue));
- Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
-
- ndnlp::Slicer slicer(1500);
- ndnlp::PacketArray pa = slicer.slice(block);
-
- BOOST_REQUIRE_EQUAL(pa->size(), 4);
-
- uint64_t seq0 = 0xdddd;
-
- size_t totalPayloadSize = 0;
-
- for (size_t i = 0; i < 4; ++i) {
- const Block& pkt = pa->at(i);
- BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
- pkt.parse();
-
- const Block::element_container& elements = pkt.elements();
- BOOST_REQUIRE_EQUAL(elements.size(), 4);
-
- const Block& sequenceElement = elements[0];
- BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
- BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));
- uint64_t seq = be64toh(*reinterpret_cast<const uint64_t*>(
- &*sequenceElement.value_begin()));
- if (i == 0) {
- seq0 = seq;
- }
- BOOST_CHECK_EQUAL(seq, seq0 + i);
-
- const Block& fragIndexElement = elements[1];
- BOOST_CHECK_EQUAL(fragIndexElement.type(), static_cast<uint32_t>(tlv::NdnlpFragIndex));
- uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
- BOOST_CHECK_EQUAL(fragIndex, i);
-
- const Block& fragCountElement = elements[2];
- BOOST_CHECK_EQUAL(fragCountElement.type(), static_cast<uint32_t>(tlv::NdnlpFragCount));
- uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
- BOOST_CHECK_EQUAL(fragCount, 4);
-
- const Block& payloadElement = elements[3];
- BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
- size_t payloadSize = payloadElement.value_size();
- totalPayloadSize += payloadSize;
- }
-
- BOOST_CHECK_EQUAL(totalPayloadSize, block.size());
-}
-
-class ReassembleFixture : protected UnitTestTimeFixture
-{
-protected:
- ReassembleFixture()
- : slicer(1500)
- , pms(time::milliseconds(100))
- {
- pms.onReceive.connect([this] (const Block& block) {
- received.push_back(block);
- });
- }
-
- Block
- makeBlock(size_t valueLength)
- {
- boost::scoped_array<uint8_t> blockValue(new uint8_t[valueLength]);
- memset(blockValue.get(), 0xcc, valueLength);
- return ndn::dataBlock(0x01, blockValue.get(), valueLength);
- }
-
- void
- receiveNdnlpData(const Block& block)
- {
- bool isOk = false;
- ndnlp::NdnlpData pkt;
- std::tie(isOk, pkt) = ndnlp::NdnlpData::fromBlock(block);
- BOOST_REQUIRE(isOk);
- pms.receive(pkt);
- }
-
-protected:
- ndnlp::Slicer slicer;
- ndnlp::PartialMessageStore pms;
-
- static const time::nanoseconds IDLE_DURATION;
-
- // received network layer packets
- std::vector<Block> received;
-};
-
-// reassemble one fragment into one Block
-BOOST_FIXTURE_TEST_CASE(Reassemble1, ReassembleFixture)
-{
- Block block = makeBlock(60);
- ndnlp::PacketArray pa = slicer.slice(block);
- BOOST_REQUIRE_EQUAL(pa->size(), 1);
-
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->receiveNdnlpData(pa->at(0));
-
- BOOST_REQUIRE_EQUAL(received.size(), 1);
- BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
- block.begin(), block.end());
-}
-
-// reassemble four and two fragments into two Blocks
-BOOST_FIXTURE_TEST_CASE(Reassemble4and2, ReassembleFixture)
-{
- Block block = makeBlock(5050);
- ndnlp::PacketArray pa = slicer.slice(block);
- BOOST_REQUIRE_EQUAL(pa->size(), 4);
-
- Block block2 = makeBlock(2000);
- ndnlp::PacketArray pa2 = slicer.slice(block2);
- BOOST_REQUIRE_EQUAL(pa2->size(), 2);
-
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->receiveNdnlpData(pa->at(0));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa2->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa2->at(0));
- BOOST_CHECK_EQUAL(received.size(), 1);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(3));
- BOOST_CHECK_EQUAL(received.size(), 1);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(2));
-
- BOOST_REQUIRE_EQUAL(received.size(), 2);
- BOOST_CHECK_EQUAL_COLLECTIONS(received.at(1).begin(), received.at(1).end(),
- block.begin(), block.end());
- BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
- block2.begin(), block2.end());
-}
-
-// reassemble four fragments into one Block, but another two fragments are expired
-BOOST_FIXTURE_TEST_CASE(ReassembleTimeout, ReassembleFixture)
-{
- Block block = makeBlock(5050);
- ndnlp::PacketArray pa = slicer.slice(block);
- BOOST_REQUIRE_EQUAL(pa->size(), 4);
-
- Block block2 = makeBlock(2000);
- ndnlp::PacketArray pa2 = slicer.slice(block2);
- BOOST_REQUIRE_EQUAL(pa2->size(), 2);
-
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->receiveNdnlpData(pa->at(0));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa2->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(1));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(3));
- BOOST_CHECK_EQUAL(received.size(), 0);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa->at(2));
- BOOST_CHECK_EQUAL(received.size(), 1);
- this->advanceClocks(time::milliseconds(40));
-
- this->receiveNdnlpData(pa2->at(0)); // last fragment was received 160ms ago, expired
- BOOST_CHECK_EQUAL(received.size(), 1);
- this->advanceClocks(time::milliseconds(40));
-
- BOOST_REQUIRE_EQUAL(received.size(), 1);
- BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
- block.begin(), block.end());
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace ndnlp
-} // namespace nfd
diff --git a/tests/daemon/face/network-interface-fixture.hpp b/tests/daemon/face/network-interface-fixture.hpp
new file mode 100644
index 0000000..3fb7af8
--- /dev/null
+++ b/tests/daemon/face/network-interface-fixture.hpp
@@ -0,0 +1,71 @@
+/* -*- 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_TESTS_NETWORK_INTERFACE_FIXTURE_HPP
+#define NFD_TESTS_NETWORK_INTERFACE_FIXTURE_HPP
+
+#include "core/network-interface.hpp"
+#include "face/ethernet-transport.hpp"
+
+#include "test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+class NetworkInterfaceFixture : protected BaseFixture
+{
+protected:
+ NetworkInterfaceFixture()
+ {
+ for (const auto& netif : listNetworkInterfaces()) {
+ if (!netif.isLoopback() && netif.isUp()) {
+ try {
+ face::EthernetTransport transport(netif, ethernet::getBroadcastAddress());
+ m_interfaces.push_back(netif);
+ }
+ catch (const face::EthernetTransport::Error&) {
+ // pass
+ }
+ }
+ }
+ }
+
+protected:
+ std::vector<NetworkInterfaceInfo> m_interfaces;
+};
+
+#define SKIP_IF_NETWORK_INTERFACE_COUNT_LT(n) \
+ do { \
+ if (this->m_interfaces.size() < (n)) { \
+ BOOST_WARN_MESSAGE(false, "skipping assertions that require " \
+ #n " or more network interfaces"); \
+ return; \
+ } \
+ } while (false)
+
+} // namespace tests
+} // namespace nfd
+
+#endif // NFD_TESTS_NETWORK_INTERFACE_FIXTURE_HPP
diff --git a/tests/daemon/mgmt/face-manager-process-config.t.cpp b/tests/daemon/mgmt/face-manager-process-config.t.cpp
index 5dedb91..b5a7312 100644
--- a/tests/daemon/mgmt/face-manager-process-config.t.cpp
+++ b/tests/daemon/mgmt/face-manager-process-config.t.cpp
@@ -47,7 +47,6 @@
m_manager.setConfigFile(m_config);
}
-public:
void
parseConfig(const std::string& type, bool isDryRun)
{
@@ -411,7 +410,6 @@
"no Ethernet multicast faces are available");
return;
}
- BOOST_CHECK_GT(factory->getMulticastFaces().size(), 0);
const std::string CONFIG_WITHOUT_MCAST =
"face_system\n"
@@ -422,6 +420,7 @@
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
+ BOOST_REQUIRE_NO_THROW(g_io.poll());
BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
}
diff --git a/tests/daemon/mgmt/manager-common-fixture.hpp b/tests/daemon/mgmt/manager-common-fixture.hpp
index ffdb579..539d56a 100644
--- a/tests/daemon/mgmt/manager-common-fixture.hpp
+++ b/tests/daemon/mgmt/manager-common-fixture.hpp
@@ -105,7 +105,7 @@
WRONG_TEXT,
WRONG_BODY_SIZE,
WRONG_BODY_VALUE
- };
+ };
/**
* @brief check a specified response data with the expected ControlResponse