From 606d5ddc9e6af77ab2fc413cb03aa01501088245 Mon Sep 17 00:00:00 2001 From: Junxiao Shi Date: Mon, 23 Sep 2019 12:47:44 -0600 Subject: [PATCH] face+fw: store and return PitToken from downstream refs #4532 Change-Id: I97b95232a242186601459622f17983d1bef806d6 --- core/common.hpp | 1 + daemon/face/generic-link-service.cpp | 18 ++++-- daemon/fw/strategy.cpp | 27 +++++++++ daemon/fw/strategy.hpp | 5 +- tests/daemon/fw/pit-token.t.cpp | 79 ++++++++++++++++++++++++++ tests/daemon/fw/topology-tester.cpp | 85 +++++++++++++++++++++------- tests/daemon/fw/topology-tester.hpp | 71 +++++++++++++++++++---- 7 files changed, 248 insertions(+), 38 deletions(-) create mode 100644 tests/daemon/fw/pit-token.t.cpp diff --git a/core/common.hpp b/core/common.hpp index efc98565..4280dc77 100644 --- a/core/common.hpp +++ b/core/common.hpp @@ -124,6 +124,7 @@ namespace scheduler = ndn::scheduler; namespace signal = ndn::util::signal; namespace time = ndn::time; using namespace ndn::time_literals; +using ndn::operator""_block; } // namespace nfd diff --git a/daemon/face/generic-link-service.cpp b/daemon/face/generic-link-service.cpp index 5a3664c5..2ab9f7ef 100644 --- a/daemon/face/generic-link-service.cpp +++ b/daemon/face/generic-link-service.cpp @@ -25,6 +25,7 @@ #include "generic-link-service.hpp" +#include #include #include @@ -129,28 +130,33 @@ void GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket) { if (m_options.allowLocalFields) { - shared_ptr incomingFaceIdTag = netPkt.getTag(); + auto incomingFaceIdTag = netPkt.getTag(); if (incomingFaceIdTag != nullptr) { lpPacket.add(*incomingFaceIdTag); } } - shared_ptr congestionMarkTag = netPkt.getTag(); + auto congestionMarkTag = netPkt.getTag(); if (congestionMarkTag != nullptr) { lpPacket.add(*congestionMarkTag); } if (m_options.allowSelfLearning) { - shared_ptr nonDiscoveryTag = netPkt.getTag(); + auto nonDiscoveryTag = netPkt.getTag(); if (nonDiscoveryTag != nullptr) { lpPacket.add(*nonDiscoveryTag); } - shared_ptr prefixAnnouncementTag = netPkt.getTag(); + auto prefixAnnouncementTag = netPkt.getTag(); if (prefixAnnouncementTag != nullptr) { lpPacket.add(*prefixAnnouncementTag); } } + + auto pitToken = netPkt.getTag(); + if (pitToken != nullptr) { + lpPacket.add(*pitToken); + } } void @@ -388,6 +394,10 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP return; } + if (firstPkt.has()) { + interest->setTag(make_shared(firstPkt.get())); + } + this->receiveInterest(*interest, endpointId); } diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp index b4ccda8e..b0b93625 100644 --- a/daemon/fw/strategy.cpp +++ b/daemon/fw/strategy.cpp @@ -27,6 +27,8 @@ #include "forwarder.hpp" #include "common/logger.hpp" +#include + #include #include @@ -191,16 +193,41 @@ Strategy::onDroppedInterest(const FaceEndpoint& egress, const Interest& interest NFD_LOG_DEBUG("onDroppedInterest out=" << egress << " name=" << interest.getName()); } +void +Strategy::sendInterest(const shared_ptr& pitEntry, + const FaceEndpoint& egress, const Interest& interest) +{ + if (interest.getTag() != nullptr) { + Interest interest2 = interest; // make a copy to preserve tag on original packet + interest2.removeTag(); + m_forwarder.onOutgoingInterest(pitEntry, egress, interest2); + return; + } + m_forwarder.onOutgoingInterest(pitEntry, egress, interest); +} + void Strategy::sendData(const shared_ptr& pitEntry, const Data& data, const FaceEndpoint& egress) { BOOST_ASSERT(pitEntry->getInterest().matchesData(data)); + shared_ptr pitToken; + auto inRecord = pitEntry->getInRecord(egress.face); + if (inRecord != pitEntry->in_end()) { + pitToken = inRecord->getInterest().getTag(); + } + // delete the PIT entry's in-record based on egress, // since Data is sent to face and endpoint from which the Interest was received pitEntry->deleteInRecord(egress.face); + if (pitToken != nullptr) { + Data data2 = data; // make a copy so each downstream can get a different PIT token + data2.setTag(pitToken); + m_forwarder.onOutgoingData(data2, egress); + return; + } m_forwarder.onOutgoingData(data, egress); } diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp index cc1b2b88..8c62329b 100644 --- a/daemon/fw/strategy.hpp +++ b/daemon/fw/strategy.hpp @@ -241,10 +241,7 @@ protected: // actions */ VIRTUAL_WITH_TESTS void sendInterest(const shared_ptr& pitEntry, - const FaceEndpoint& egress, const Interest& interest) - { - m_forwarder.onOutgoingInterest(pitEntry, egress, interest); - } + const FaceEndpoint& egress, const Interest& interest); /** \brief send \p data to \p egress * \param pitEntry PIT entry diff --git a/tests/daemon/fw/pit-token.t.cpp b/tests/daemon/fw/pit-token.t.cpp new file mode 100644 index 00000000..aa735ed1 --- /dev/null +++ b/tests/daemon/fw/pit-token.t.cpp @@ -0,0 +1,79 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014-2019, 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 . + */ + +#include "tests/daemon/global-io-fixture.hpp" +#include "topology-tester.hpp" + +#include +#include + +namespace nfd { +namespace fw { +namespace tests { + +using namespace nfd::tests; + +BOOST_AUTO_TEST_SUITE(Fw) +BOOST_AUTO_TEST_SUITE(TestPitToken) + +// Downstream requires PIT token. +BOOST_FIXTURE_TEST_CASE(Downstream, GlobalIoTimeFixture) +{ + TopologyTester topo; + TopologyNode nodeR = topo.addForwarder("R"); + auto linkC = topo.addBareLink("C", nodeR, ndn::nfd::FACE_SCOPE_NON_LOCAL); + auto linkS = topo.addBareLink("S", nodeR, ndn::nfd::FACE_SCOPE_NON_LOCAL); + topo.registerPrefix(nodeR, linkS->getForwarderFace(), "/U", 5); + // Client --- Router --- Server + // Client requires PIT token; Router supports PIT token; Server disallows PIT token. + + // C sends Interest /U/0 with PIT token + lp::Packet lppI("6414 pit-token=6206A0A1A2A3A4A5 payload=500A interest=0508 0706080155080130"_block); + lp::PitToken tokenI(lppI.get()); + linkC->receivePacket(lppI.wireEncode()); + advanceClocks(5_ms, 30_ms); + + // S should receive Interest without PIT token + BOOST_REQUIRE_EQUAL(linkS->sentPackets.size(), 1); + lp::Packet lppS(linkS->sentPackets.front()); + BOOST_CHECK_EQUAL(lppS.count(), 0); + + // S responds Data + linkS->receivePacket(makeData("/U/0")->wireEncode()); + advanceClocks(5_ms, 30_ms); + + // C should receive Data with same PIT token + BOOST_REQUIRE_EQUAL(linkC->sentPackets.size(), 1); + lp::Packet lppD(linkC->sentPackets.front()); + lp::PitToken tokenD(lppD.get()); + BOOST_CHECK(tokenD == tokenI); +} + +BOOST_AUTO_TEST_SUITE_END() // TestPitToken +BOOST_AUTO_TEST_SUITE_END() // Fw + +} // namespace tests +} // namespace fw +} // namespace nfd diff --git a/tests/daemon/fw/topology-tester.cpp b/tests/daemon/fw/topology-tester.cpp index 3007f389..6a70ead4 100644 --- a/tests/daemon/fw/topology-tester.cpp +++ b/tests/daemon/fw/topology-tester.cpp @@ -104,9 +104,14 @@ TopologyLink::transmit(TopologyNode i, const Block& packet) } } -TopologyAppLink::TopologyAppLink(shared_ptr forwarderFace) +TopologySingleLink::TopologySingleLink(shared_ptr forwarderFace) : m_face(std::move(forwarderFace)) , m_forwarderTransport(static_cast(m_face->getTransport())) +{ +} + +TopologyAppLink::TopologyAppLink(shared_ptr forwarderFace) + : TopologySingleLink(std::move(forwarderFace)) , m_clientTransport(make_shared()) , m_client(make_shared(m_clientTransport, getGlobalIoService())) { @@ -125,6 +130,38 @@ TopologyAppLink::recover() m_clientTransport->connectToForwarder(m_forwarderTransport); } +class TopologyBareLink::Observer : public face::InternalTransportBase +{ +public: + explicit + Observer(std::vector& receivedPackets) + : m_receivedPackets(receivedPackets) + { + } + + void + receivePacket(const Block& packet) final + { + m_receivedPackets.push_back(packet); + } + +private: + std::vector& m_receivedPackets; +}; + +TopologyBareLink::TopologyBareLink(shared_ptr forwarderFace) + : TopologySingleLink(std::move(forwarderFace)) + , m_observer(make_unique(sentPackets)) +{ + m_forwarderTransport->setPeer(m_observer.get()); +} + +void +TopologyBareLink::receivePacket(const Block& packet) +{ + m_forwarderTransport->receivePacket(packet); +} + class TopologyPcapLinkService : public GenericLinkService , public TopologyPcap { @@ -166,6 +203,19 @@ TopologyTester::addForwarder(const std::string& label) return i; } +shared_ptr +TopologyTester::makeFace(TopologyNode i, const FaceUri& localUri, const FaceUri& remoteUri, + ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType) +{ + Forwarder& forwarder = this->getForwarder(i); + unique_ptr service = m_wantPcap ? make_unique() : + make_unique(); + auto transport = make_unique(localUri, remoteUri, scope, linkType); + auto face = make_shared(std::move(service), std::move(transport)); + forwarder.addFace(face); + return face; +} + shared_ptr TopologyTester::addLink(const std::string& label, time::nanoseconds delay, std::initializer_list forwarders, @@ -180,16 +230,8 @@ TopologyTester::addLink(const std::string& label, time::nanoseconds delay, BOOST_ASSERT(forwarders.size() <= 2 || linkType != ndn::nfd::LINK_TYPE_POINT_TO_POINT); for (TopologyNode i : forwarders) { - Forwarder& forwarder = this->getForwarder(i); FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/" + label); - - unique_ptr service = m_wantPcap ? make_unique() : - make_unique(); - auto transport = make_unique(localUri, remoteUri, - ndn::nfd::FACE_SCOPE_NON_LOCAL, linkType); - auto face = make_shared(std::move(service), std::move(transport)); - - forwarder.addFace(face); + auto face = makeFace(i, localUri, remoteUri, ndn::nfd::FACE_SCOPE_NON_LOCAL, linkType); link->addFace(i, std::move(face)); } @@ -200,17 +242,9 @@ TopologyTester::addLink(const std::string& label, time::nanoseconds delay, shared_ptr TopologyTester::addAppFace(const std::string& label, TopologyNode i) { - Forwarder& forwarder = this->getForwarder(i); FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/local/" + label); FaceUri remoteUri("topology://" + m_forwarderLabels.at(i) + "/app/" + label); - - unique_ptr service = m_wantPcap ? make_unique() : - make_unique(); - auto transport = make_unique(localUri, remoteUri, - ndn::nfd::FACE_SCOPE_LOCAL, ndn::nfd::LINK_TYPE_POINT_TO_POINT); - auto face = make_shared(std::move(service), std::move(transport)); - - forwarder.addFace(face); + auto face = makeFace(i, localUri, remoteUri, ndn::nfd::FACE_SCOPE_LOCAL, ndn::nfd::LINK_TYPE_POINT_TO_POINT); auto al = make_shared(std::move(face)); m_appLinks.push_back(al); // keep a shared_ptr so callers don't have to @@ -225,6 +259,19 @@ TopologyTester::addAppFace(const std::string& label, TopologyNode i, const Name& return al; } +shared_ptr +TopologyTester::addBareLink(const std::string& label, TopologyNode i, ndn::nfd::FaceScope scope, + ndn::nfd::LinkType linkType) +{ + FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/local/" + label); + FaceUri remoteUri("topology://" + m_forwarderLabels.at(i) + "/bare/" + label); + auto face = makeFace(i, localUri, remoteUri, scope, linkType); + + auto bl = make_shared(std::move(face)); + m_bareLinks.push_back(bl); // keep a shared_ptr so callers don't have to + return bl; +} + void TopologyTester::enablePcap(bool isEnabled) { diff --git a/tests/daemon/fw/topology-tester.hpp b/tests/daemon/fw/topology-tester.hpp index 233c2167..92434763 100644 --- a/tests/daemon/fw/topology-tester.hpp +++ b/tests/daemon/fw/topology-tester.hpp @@ -150,9 +150,33 @@ private: std::unordered_map m_transports; }; +/** \brief represents a link on a single forwarder + */ +class TopologySingleLink : noncopyable +{ +public: + /** \brief constructor + * \param forwarderFace a Face with InternalForwarderTransport + */ + explicit + TopologySingleLink(shared_ptr forwarderFace); + + /** \return face on forwarder side + */ + Face& + getForwarderFace() + { + return *m_face; + } + +protected: + shared_ptr m_face; + face::InternalForwarderTransport* m_forwarderTransport; +}; + /** \brief represents a link to a local application */ -class TopologyAppLink : noncopyable +class TopologyAppLink : public TopologySingleLink { public: /** \brief constructor @@ -171,14 +195,6 @@ public: void recover(); - /** \return face on forwarder side - */ - Face& - getForwarderFace() - { - return *m_face; - } - /** \return face on application side */ ndn::Face& @@ -188,12 +204,32 @@ public: } private: - shared_ptr m_face; - face::InternalForwarderTransport* m_forwarderTransport; shared_ptr m_clientTransport; shared_ptr m_client; }; +/** \brief allows the test case to inject and observe L2 packets on a link + */ +class TopologyBareLink : public TopologySingleLink +{ +public: + /** \brief constructor + * \param forwarderFace a Face with InternalForwarderTransport + */ + explicit + TopologyBareLink(shared_ptr forwarderFace); + + void + receivePacket(const Block& packet); + +public: + std::vector sentPackets; + +private: + class Observer; + unique_ptr m_observer; +}; + /** \brief captured packets on a face */ class TopologyPcap : noncopyable @@ -264,6 +300,13 @@ public: shared_ptr addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost = 0); + /** \brief makes a link that allows the test case to inject and observe L2 packets + */ + shared_ptr + addBareLink(const std::string& label, TopologyNode i, + ndn::nfd::FaceScope scope = ndn::nfd::FACE_SCOPE_LOCAL, + ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT); + /** \brief enables packet capture on every forwarder face */ void @@ -293,12 +336,18 @@ public: addIntervalConsumer(ndn::Face& face, const Name& prefix, time::nanoseconds interval, size_t n, int seq = -1); +private: + shared_ptr + makeFace(TopologyNode i, const FaceUri& localUri, const FaceUri& remoteUri, + ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType); + private: bool m_wantPcap = false; std::vector> m_forwarders; std::vector m_forwarderLabels; std::vector> m_links; std::vector> m_appLinks; + std::vector> m_bareLinks; }; } // namespace tests