blob: 698a52571b068c7a22803e7c3b0854b6aeb8f00f [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, 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 "mgmt/face-manager.hpp"
#include "face/generic-link-service.hpp"
#include "face-manager-command-fixture.hpp"
#include "nfd-manager-common-fixture.hpp"
namespace nfd {
namespace tests {
BOOST_AUTO_TEST_SUITE(Mgmt)
BOOST_AUTO_TEST_SUITE(TestFaceManager)
BOOST_FIXTURE_TEST_SUITE(CreateFace, BaseFixture)
class TcpFaceOnDemand
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
}
};
class TcpFacePersistent
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
}
};
class TcpFacePermanent
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
}
};
class UdpFaceOnDemand
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
}
};
class UdpFacePersistent
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
}
};
class UdpFacePermanent
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
}
};
class LocalTcpFaceLocalFieldsEnabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);
}
};
class LocalTcpFaceLocalFieldsDisabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);
}
};
class NonLocalUdpFaceLocalFieldsEnabled // won't work because non-local scope
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);
}
};
class NonLocalUdpFaceLocalFieldsDisabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);
}
};
class TcpFaceLpReliabilityEnabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);
}
};
class TcpFaceLpReliabilityDisabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);
}
};
class UdpFaceLpReliabilityEnabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);
}
};
class UdpFaceLpReliabilityDisabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);
}
};
class TcpFaceCongestionMarkingEnabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setBaseCongestionMarkingInterval(50_ms)
.setDefaultCongestionThreshold(1000)
.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true);
}
};
class TcpFaceCongestionMarkingDisabled
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:26363")
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setBaseCongestionMarkingInterval(50_ms)
.setDefaultCongestionThreshold(1000)
.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, false);
}
};
class FaceUriMalformed
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("tcp4://127.0.0.1:not-a-port");
}
};
class FaceUriNonCanonical
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("udp://localhost");
}
};
class FaceUriUnsupportedScheme
{
public:
static ControlParameters
getParameters()
{
return ControlParameters()
.setUri("dev://eth0");
}
};
namespace mpl = boost::mpl;
// pairs of CreateCommand and Success/Failure status
using TestCases = mpl::vector<
mpl::pair<TcpFaceOnDemand, CommandFailure<406>>,
mpl::pair<TcpFacePersistent, CommandSuccess>,
mpl::pair<TcpFacePermanent, CommandSuccess>,
mpl::pair<UdpFaceOnDemand, CommandFailure<406>>,
mpl::pair<UdpFacePersistent, CommandSuccess>,
mpl::pair<UdpFacePermanent, CommandSuccess>,
mpl::pair<LocalTcpFaceLocalFieldsEnabled, CommandSuccess>,
mpl::pair<LocalTcpFaceLocalFieldsDisabled, CommandSuccess>,
mpl::pair<NonLocalUdpFaceLocalFieldsEnabled, CommandFailure<406>>,
mpl::pair<NonLocalUdpFaceLocalFieldsDisabled, CommandSuccess>,
mpl::pair<TcpFaceLpReliabilityEnabled, CommandSuccess>,
mpl::pair<TcpFaceLpReliabilityDisabled, CommandSuccess>,
mpl::pair<UdpFaceLpReliabilityEnabled, CommandSuccess>,
mpl::pair<UdpFaceLpReliabilityDisabled, CommandSuccess>,
mpl::pair<TcpFaceCongestionMarkingEnabled, CommandSuccess>,
mpl::pair<TcpFaceCongestionMarkingDisabled, CommandSuccess>,
mpl::pair<FaceUriMalformed, CommandFailure<400>>,
mpl::pair<FaceUriNonCanonical, CommandFailure<400>>,
mpl::pair<FaceUriUnsupportedScheme, CommandFailure<406>>>;
BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, TestCases, FaceManagerCommandFixture)
{
using FaceType = typename T::first;
using CreateResult = typename T::second;
Interest req = makeControlCommandRequest("/localhost/nfd/faces/create", FaceType::getParameters());
bool hasCallbackFired = false;
this->node1.face.onSendData.connect([this, req, &hasCallbackFired] (const Data& response) {
if (!req.getName().isPrefixOf(response.getName())) {
return;
}
ControlResponse actual(response.getContent().blockFromValue());
ControlResponse expected(CreateResult::getExpected());
BOOST_TEST_MESSAGE(actual.getText());
BOOST_CHECK_EQUAL(expected.getCode(), actual.getCode());
if (actual.getBody().hasWire()) {
ControlParameters expectedParams(FaceType::getParameters());
ControlParameters actualParams(actual.getBody());
BOOST_CHECK(actualParams.hasFaceId());
BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
if (actual.getCode() == 200) {
if (expectedParams.hasFlags()) {
BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED),
actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED),
actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED));
BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED),
actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
}
else {
// local fields are disabled by default
BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED), false);
BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED), false);
BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED), false);
}
if (expectedParams.hasBaseCongestionMarkingInterval()) {
BOOST_CHECK_EQUAL(expectedParams.getBaseCongestionMarkingInterval(),
actualParams.getBaseCongestionMarkingInterval());
}
else {
BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), 100_ms);
}
if (expectedParams.hasDefaultCongestionThreshold()) {
BOOST_CHECK_EQUAL(expectedParams.getDefaultCongestionThreshold(),
actualParams.getDefaultCongestionThreshold());
}
else {
BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 65536);
}
}
else {
BOOST_CHECK_EQUAL(expectedParams.getUri(), actualParams.getUri());
}
}
if (actual.getCode() != 200) {
FaceUri uri;
if (uri.parse(FaceType::getParameters().getUri())) {
// ensure face not created
const auto& faceTable = this->node1.faceTable;
BOOST_CHECK(std::none_of(faceTable.begin(), faceTable.end(), [uri] (Face& face) {
return face.getRemoteUri() == uri;
}));
}
else {
// do not check malformed FaceUri
}
}
hasCallbackFired = true;
});
this->node1.face.receive(req);
this->advanceClocks(1_ms, 5);
BOOST_CHECK(hasCallbackFired);
}
BOOST_FIXTURE_TEST_CASE(ExistingFace, FaceManagerCommandFixture)
{
using FaceType = UdpFacePersistent;
{
// create face
Interest req = makeControlCommandRequest("/localhost/nfd/faces/create", FaceType::getParameters());
this->node1.face.receive(req);
this->advanceClocks(1_ms, 5);
}
// find the created face
auto foundFace = this->node1.findFaceByUri(FaceType::getParameters().getUri());
BOOST_REQUIRE(foundFace != nullptr);
{
// re-create face
Interest req = makeControlCommandRequest("/localhost/nfd/faces/create", FaceType::getParameters());
bool hasCallbackFired = false;
this->node1.face.onSendData.connect(
[req, foundFace, &hasCallbackFired] (const Data& response) {
if (!req.getName().isPrefixOf(response.getName())) {
return;
}
ControlResponse actual(response.getContent().blockFromValue());
BOOST_REQUIRE_EQUAL(actual.getCode(), 409);
ControlParameters actualParams(actual.getBody());
BOOST_CHECK_EQUAL(foundFace->getId(), actualParams.getFaceId());
BOOST_CHECK_EQUAL(foundFace->getRemoteUri().toString(), actualParams.getUri());
BOOST_CHECK_EQUAL(foundFace->getPersistency(), actualParams.getFacePersistency());
auto linkService = dynamic_cast<face::GenericLinkService*>(foundFace->getLinkService());
BOOST_CHECK_EQUAL(linkService->getOptions().baseCongestionMarkingInterval,
actualParams.getBaseCongestionMarkingInterval());
BOOST_CHECK_EQUAL(linkService->getOptions().defaultCongestionThreshold,
actualParams.getDefaultCongestionThreshold());
hasCallbackFired = true;
});
this->node1.face.receive(req);
this->advanceClocks(1_ms, 5);
BOOST_CHECK(hasCallbackFired);
}
}
BOOST_AUTO_TEST_SUITE_END() // CreateFace
BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // namespace tests
} // namespace nfd