blob: 41d5d8c61708945c36e68432b442b9bf55f8f385 [file] [log] [blame]
Junxiao Shi5e5e4452015-09-24 16:56:52 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe4b22382018-06-10 14:37:24 -04002/*
3 * Copyright (c) 2014-2018, Regents of the University of California,
Junxiao Shi5e5e4452015-09-24 16:56:52 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "topology-tester.hpp"
Junxiao Shi5e5e4452015-09-24 16:56:52 -070027#include "face/generic-link-service.hpp"
28
Davide Pesaventoe4b22382018-06-10 14:37:24 -040029#include <ndn-cxx/encoding/encoding-buffer-fwd.hpp>
30
Junxiao Shi5e5e4452015-09-24 16:56:52 -070031namespace nfd {
32namespace fw {
33namespace tests {
34
Junxiao Shi6535f1e2015-10-08 13:02:18 -070035using face::InternalTransportBase;
36using face::InternalForwarderTransport;
37using face::InternalClientTransport;
Junxiao Shi6535f1e2015-10-08 13:02:18 -070038using face::GenericLinkService;
Junxiao Shi5e5e4452015-09-24 16:56:52 -070039
Teng Liangf995f382017-04-04 22:09:39 +000040TopologyLink::TopologyLink(time::nanoseconds delay)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070041 : m_isUp(true)
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070042{
43 this->setDelay(delay);
44}
45
46void
Teng Liangf995f382017-04-04 22:09:39 +000047TopologyLink::block(TopologyNode i, TopologyNode j)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070048{
Teng Liangf995f382017-04-04 22:09:39 +000049 m_transports.at(i).blockedDestinations.insert(j);
50}
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070051
Teng Liangf995f382017-04-04 22:09:39 +000052void
53TopologyLink::unblock(TopologyNode i, TopologyNode j)
54{
55 m_transports.at(i).blockedDestinations.erase(j);
56}
57
58void
59TopologyLink::setDelay(time::nanoseconds delay)
60{
61 BOOST_ASSERT(delay > time::nanoseconds::zero()); // zero delay does not work on macOS
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070062 m_delay = delay;
Junxiao Shi5e5e4452015-09-24 16:56:52 -070063}
64
65void
Junxiao Shicde37ad2015-12-24 01:02:05 -070066TopologyLink::addFace(TopologyNode i, shared_ptr<Face> face)
Junxiao Shi6535f1e2015-10-08 13:02:18 -070067{
Junxiao Shi5e5e4452015-09-24 16:56:52 -070068 BOOST_ASSERT(m_transports.count(i) == 0);
Teng Liangf995f382017-04-04 22:09:39 +000069 auto& nodeTransport = m_transports[i];
Junxiao Shi5e5e4452015-09-24 16:56:52 -070070
Teng Liangf995f382017-04-04 22:09:39 +000071 nodeTransport.face = face;
72
73 nodeTransport.transport = dynamic_cast<InternalTransportBase*>(face->getTransport());
74 BOOST_ASSERT(nodeTransport.transport != nullptr);
75 nodeTransport.transport->afterSend.connect(
76 [this, i] (const Block& packet) { this->transmit(i, packet); });
Junxiao Shi5e5e4452015-09-24 16:56:52 -070077}
78
79void
Junxiao Shi6535f1e2015-10-08 13:02:18 -070080TopologyLink::transmit(TopologyNode i, const Block& packet)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070081{
82 if (!m_isUp) {
83 return;
84 }
85
Teng Liangf995f382017-04-04 22:09:39 +000086 const auto& blockedDestinations = m_transports.at(i).blockedDestinations;
87
Davide Pesavento97210d52016-10-14 15:45:48 +020088 for (const auto& p : m_transports) {
Teng Liangf995f382017-04-04 22:09:39 +000089 if (p.first == i || blockedDestinations.count(p.first) > 0) {
Junxiao Shi5e5e4452015-09-24 16:56:52 -070090 continue;
91 }
92
Teng Liangf995f382017-04-04 22:09:39 +000093 InternalTransportBase* recipient = p.second.transport;
Junxiao Shi5e5e4452015-09-24 16:56:52 -070094 this->scheduleReceive(recipient, packet);
95 }
96}
97
Junxiao Shi5e5e4452015-09-24 16:56:52 -070098void
Junxiao Shi6535f1e2015-10-08 13:02:18 -070099TopologyLink::scheduleReceive(InternalTransportBase* recipient, const Block& packet)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700100{
101 scheduler::schedule(m_delay, [packet, recipient] {
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700102 recipient->receiveFromLink(packet);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700103 });
104}
105
Junxiao Shicde37ad2015-12-24 01:02:05 -0700106TopologyAppLink::TopologyAppLink(shared_ptr<Face> forwarderFace)
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700107 : m_face(forwarderFace)
Junxiao Shicde37ad2015-12-24 01:02:05 -0700108 , m_forwarderTransport(static_cast<InternalForwarderTransport*>(forwarderFace->getTransport()))
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700109 , m_clientTransport(make_shared<InternalClientTransport>())
110 , m_client(make_shared<ndn::Face>(m_clientTransport, getGlobalIoService()))
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700111{
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700112 this->recover();
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700113}
114
115void
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700116TopologyAppLink::fail()
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700117{
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700118 m_clientTransport->connectToForwarder(nullptr);
119}
120
121void
122TopologyAppLink::recover()
123{
124 m_clientTransport->connectToForwarder(m_forwarderTransport);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700125}
126
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000127class TopologyPcapLinkService : public GenericLinkService
128 , public TopologyPcap
129{
130private:
131 ///\todo #3941 call GenericLinkServiceCounters constructor in TopologyPcapLinkService constructor
132
133 void
134 doSendInterest(const Interest& interest) override
135 {
136 this->sentInterests.push_back(interest);
137 this->sentInterests.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
138 this->GenericLinkService::doSendInterest(interest);
139 }
140
141 void
142 doSendData(const Data& data) override
143 {
144 this->sentData.push_back(data);
145 this->sentData.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
146 this->GenericLinkService::doSendData(data);
147 }
148
149 void
150 doSendNack(const lp::Nack& nack) override
151 {
152 this->sentNacks.push_back(nack);
153 this->sentNacks.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
154 this->GenericLinkService::doSendNack(nack);
155 }
156};
157
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700158TopologyNode
159TopologyTester::addForwarder(const std::string& label)
160{
161 size_t i = m_forwarders.size();
Davide Pesavento459cf192016-03-03 02:20:12 +0100162 m_forwarders.push_back(make_unique<Forwarder>());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700163 m_forwarderLabels.push_back(label);
164 BOOST_ASSERT(m_forwarders.size() == m_forwarderLabels.size());
165 return i;
166}
167
168shared_ptr<TopologyLink>
Teng Liangf995f382017-04-04 22:09:39 +0000169TopologyTester::addLink(const std::string& label, time::nanoseconds delay,
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700170 std::initializer_list<TopologyNode> forwarders,
Teng Liangf995f382017-04-04 22:09:39 +0000171 ndn::nfd::LinkType linkType)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700172{
Yumin Xiaab497452016-05-10 20:23:24 +0800173 auto link = std::make_shared<TopologyLink>(delay);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700174 FaceUri remoteUri("topology://link/" + label);
Teng Liangf995f382017-04-04 22:09:39 +0000175 if (linkType == ndn::nfd::LINK_TYPE_NONE) {
176 linkType = forwarders.size() > 2 ? ndn::nfd::LINK_TYPE_MULTI_ACCESS :
177 ndn::nfd::LINK_TYPE_POINT_TO_POINT;
178 }
179 BOOST_ASSERT(forwarders.size() <= 2 || linkType != ndn::nfd::LINK_TYPE_POINT_TO_POINT);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700180
181 for (TopologyNode i : forwarders) {
182 Forwarder& forwarder = this->getForwarder(i);
183 FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/" + label);
184
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000185 unique_ptr<GenericLinkService> service = m_wantPcap ? make_unique<TopologyPcapLinkService>() :
186 make_unique<GenericLinkService>();
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700187 auto transport = make_unique<InternalForwarderTransport>(localUri, remoteUri,
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700188 ndn::nfd::FACE_SCOPE_NON_LOCAL, linkType);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700189 auto face = make_shared<Face>(std::move(service), std::move(transport));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700190
Junxiao Shicde37ad2015-12-24 01:02:05 -0700191 forwarder.addFace(face);
192 link->addFace(i, face);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700193 }
194
195 m_links.push_back(link); // keep a shared_ptr so callers don't have to
196 return link;
197}
198
199shared_ptr<TopologyAppLink>
200TopologyTester::addAppFace(const std::string& label, TopologyNode i)
201{
202 Forwarder& forwarder = this->getForwarder(i);
203 FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/local/" + label);
204 FaceUri remoteUri("topology://" + m_forwarderLabels.at(i) + "/app/" + label);
205
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000206 unique_ptr<GenericLinkService> service = m_wantPcap ? make_unique<TopologyPcapLinkService>() :
207 make_unique<GenericLinkService>();
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700208 auto transport = make_unique<InternalForwarderTransport>(localUri, remoteUri,
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700209 ndn::nfd::FACE_SCOPE_LOCAL, ndn::nfd::LINK_TYPE_POINT_TO_POINT);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700210 auto face = make_shared<Face>(std::move(service), std::move(transport));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700211
Junxiao Shicde37ad2015-12-24 01:02:05 -0700212 forwarder.addFace(face);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700213
Junxiao Shicde37ad2015-12-24 01:02:05 -0700214 auto al = make_shared<TopologyAppLink>(face);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700215 m_appLinks.push_back(al); // keep a shared_ptr so callers don't have to
216 return al;
217}
218
219shared_ptr<TopologyAppLink>
220TopologyTester::addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost)
221{
222 shared_ptr<TopologyAppLink> al = this->addAppFace(label, i);
223 this->registerPrefix(i, al->getForwarderFace(), prefix, cost);
224 return al;
225}
226
227void
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000228TopologyTester::enablePcap(bool isEnabled)
229{
230 m_wantPcap = isEnabled;
231}
232
233TopologyPcap&
234TopologyTester::getPcap(const Face& face)
235{
236 return dynamic_cast<TopologyPcapLinkService&>(*face.getLinkService());
237}
238
239void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700240TopologyTester::registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost)
241{
242 Forwarder& forwarder = this->getForwarder(i);
243 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000244 fib.insert(prefix).first->addNextHop(const_cast<Face&>(face), cost);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700245}
246
247void
248TopologyTester::addEchoProducer(ndn::Face& face, const Name& prefix)
249{
250 face.setInterestFilter(prefix,
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400251 [&face] (const auto&, const Interest& interest) {
252 auto data = makeData(interest.getName());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700253 face.put(*data);
254 });
255}
256
257void
258TopologyTester::addIntervalConsumer(ndn::Face& face, const Name& prefix,
Teng Liangf995f382017-04-04 22:09:39 +0000259 time::nanoseconds interval, size_t n, int seq)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700260{
261 Name name(prefix);
Teng Liangf995f382017-04-04 22:09:39 +0000262 if (seq >= 0) {
263 name.appendSequenceNumber(seq);
264 ++seq;
265 }
266 else {
267 name.appendTimestamp();
268 }
269
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400270 auto interest = makeInterest(name);
Junxiao Shi9ede5bd2016-08-09 03:51:27 +0000271 face.expressInterest(*interest, nullptr, nullptr, nullptr);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700272
273 if (n > 1) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400274 scheduler::schedule(interval,
275 [=, &face] { addIntervalConsumer(face, prefix, interval, n - 1, seq); });
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700276 }
277}
278
279} // namespace tests
280} // namespace fw
281} // namespace nfd