blob: a7ff33a7dcc8d246d5f6e7796e97583ea8997850 [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/*
Davide Pesavento0a05f7a2023-10-16 20:28:06 -04003 * Copyright (c) 2014-2023, 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"
Davide Pesavento284bd622019-03-31 02:10:02 -040027
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040028#include "common/global.hpp"
Junxiao Shi5e5e4452015-09-24 16:56:52 -070029#include "face/generic-link-service.hpp"
30
Davide Pesaventoe4b22382018-06-10 14:37:24 -040031#include <ndn-cxx/encoding/encoding-buffer-fwd.hpp>
32
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040033namespace nfd::tests {
Junxiao Shi5e5e4452015-09-24 16:56:52 -070034
Junxiao Shi6535f1e2015-10-08 13:02:18 -070035using face::GenericLinkService;
Davide Pesavento284bd622019-03-31 02:10:02 -040036using face::InternalClientTransport;
37using face::InternalForwarderTransport;
38
39TopologyLink::NodeTransport::NodeTransport(shared_ptr<Face> f, ReceiveProxy::Callback cb)
40 : face(std::move(f))
41 , transport(dynamic_cast<InternalForwarderTransport*>(face->getTransport()))
42 , proxy(std::move(cb))
43{
44 BOOST_ASSERT(transport != nullptr);
45}
Junxiao Shi5e5e4452015-09-24 16:56:52 -070046
Teng Liangf995f382017-04-04 22:09:39 +000047TopologyLink::TopologyLink(time::nanoseconds delay)
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070048{
49 this->setDelay(delay);
50}
51
52void
Teng Liangf995f382017-04-04 22:09:39 +000053TopologyLink::block(TopologyNode i, TopologyNode j)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070054{
Teng Liangf995f382017-04-04 22:09:39 +000055 m_transports.at(i).blockedDestinations.insert(j);
56}
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070057
Teng Liangf995f382017-04-04 22:09:39 +000058void
59TopologyLink::unblock(TopologyNode i, TopologyNode j)
60{
61 m_transports.at(i).blockedDestinations.erase(j);
62}
63
64void
65TopologyLink::setDelay(time::nanoseconds delay)
66{
67 BOOST_ASSERT(delay > time::nanoseconds::zero()); // zero delay does not work on macOS
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070068 m_delay = delay;
Junxiao Shi5e5e4452015-09-24 16:56:52 -070069}
70
71void
Junxiao Shicde37ad2015-12-24 01:02:05 -070072TopologyLink::addFace(TopologyNode i, shared_ptr<Face> face)
Junxiao Shi6535f1e2015-10-08 13:02:18 -070073{
Davide Pesaventob3a23ca2019-05-04 20:40:21 -040074 auto receiveCb = [this, i] (const Block& packet) { transmit(i, packet); };
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040075 auto ret = m_transports.try_emplace(i, std::move(face), std::move(receiveCb));
Davide Pesavento284bd622019-03-31 02:10:02 -040076 BOOST_ASSERT(ret.second);
Teng Liangf995f382017-04-04 22:09:39 +000077
Davide Pesavento284bd622019-03-31 02:10:02 -040078 auto& node = ret.first->second;
79 node.transport->setPeer(&node.proxy);
Junxiao Shi5e5e4452015-09-24 16:56:52 -070080}
81
82void
Davide Pesaventob3a23ca2019-05-04 20:40:21 -040083TopologyLink::transmit(TopologyNode i, const Block& packet)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070084{
85 if (!m_isUp) {
86 return;
87 }
88
Teng Liangf995f382017-04-04 22:09:39 +000089 const auto& blockedDestinations = m_transports.at(i).blockedDestinations;
90
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040091 for (const auto& [node, transport] : m_transports) {
92 if (node == i || blockedDestinations.count(node) > 0) {
Junxiao Shi5e5e4452015-09-24 16:56:52 -070093 continue;
94 }
95
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040096 getScheduler().schedule(m_delay, [packet, recipient = transport.transport] {
Davide Pesaventob3a23ca2019-05-04 20:40:21 -040097 recipient->receivePacket(packet);
98 });
Junxiao Shi5e5e4452015-09-24 16:56:52 -070099 }
100}
101
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600102TopologySingleLink::TopologySingleLink(shared_ptr<Face> forwarderFace)
Davide Pesavento284bd622019-03-31 02:10:02 -0400103 : m_face(std::move(forwarderFace))
104 , m_forwarderTransport(static_cast<InternalForwarderTransport*>(m_face->getTransport()))
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600105{
106}
107
108TopologyAppLink::TopologyAppLink(shared_ptr<Face> forwarderFace)
109 : TopologySingleLink(std::move(forwarderFace))
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700110 , m_clientTransport(make_shared<InternalClientTransport>())
111 , m_client(make_shared<ndn::Face>(m_clientTransport, getGlobalIoService()))
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700112{
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700113 this->recover();
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700114}
115
116void
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700117TopologyAppLink::fail()
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700118{
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700119 m_clientTransport->connectToForwarder(nullptr);
120}
121
122void
123TopologyAppLink::recover()
124{
125 m_clientTransport->connectToForwarder(m_forwarderTransport);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700126}
127
Davide Pesavento0a05f7a2023-10-16 20:28:06 -0400128class TopologyBareLink::Observer final : public face::InternalTransportBase
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600129{
130public:
131 explicit
132 Observer(std::vector<Block>& receivedPackets)
133 : m_receivedPackets(receivedPackets)
134 {
135 }
136
137 void
138 receivePacket(const Block& packet) final
139 {
140 m_receivedPackets.push_back(packet);
141 }
142
143private:
144 std::vector<Block>& m_receivedPackets;
145};
146
147TopologyBareLink::TopologyBareLink(shared_ptr<Face> forwarderFace)
148 : TopologySingleLink(std::move(forwarderFace))
149 , m_observer(make_unique<Observer>(sentPackets))
150{
151 m_forwarderTransport->setPeer(m_observer.get());
152}
153
154void
155TopologyBareLink::receivePacket(const Block& packet)
156{
157 m_forwarderTransport->receivePacket(packet);
158}
159
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000160class TopologyPcapLinkService : public GenericLinkService
161 , public TopologyPcap
162{
163private:
164 ///\todo #3941 call GenericLinkServiceCounters constructor in TopologyPcapLinkService constructor
165
166 void
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700167 doSendInterest(const Interest& interest) override
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000168 {
169 this->sentInterests.push_back(interest);
170 this->sentInterests.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700171 this->GenericLinkService::doSendInterest(interest);
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000172 }
173
174 void
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700175 doSendData(const Data& data) override
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000176 {
177 this->sentData.push_back(data);
178 this->sentData.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700179 this->GenericLinkService::doSendData(data);
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000180 }
181
182 void
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700183 doSendNack(const lp::Nack& nack) override
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000184 {
185 this->sentNacks.push_back(nack);
186 this->sentNacks.back().setTag(std::make_shared<TopologyPcapTimestamp>(time::steady_clock::now()));
Teng Liangf3bc3ae2020-06-08 10:19:25 -0700187 this->GenericLinkService::doSendNack(nack);
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000188 }
189};
190
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700191TopologyNode
192TopologyTester::addForwarder(const std::string& label)
193{
194 size_t i = m_forwarders.size();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400195 m_forwarders.push_back(make_unique<TopologyForwarder>(label));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700196 return i;
197}
198
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600199shared_ptr<Face>
200TopologyTester::makeFace(TopologyNode i, const FaceUri& localUri, const FaceUri& remoteUri,
201 ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType)
202{
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600203 unique_ptr<GenericLinkService> service = m_wantPcap ? make_unique<TopologyPcapLinkService>() :
204 make_unique<GenericLinkService>();
205 auto transport = make_unique<InternalForwarderTransport>(localUri, remoteUri, scope, linkType);
206 auto face = make_shared<Face>(std::move(service), std::move(transport));
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400207 m_forwarders.at(i)->faceTable.add(face);
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600208 return face;
209}
210
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700211shared_ptr<TopologyLink>
Teng Liangf995f382017-04-04 22:09:39 +0000212TopologyTester::addLink(const std::string& label, time::nanoseconds delay,
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700213 std::initializer_list<TopologyNode> forwarders,
Teng Liangf995f382017-04-04 22:09:39 +0000214 ndn::nfd::LinkType linkType)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700215{
Yumin Xiaab497452016-05-10 20:23:24 +0800216 auto link = std::make_shared<TopologyLink>(delay);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700217 FaceUri remoteUri("topology://link/" + label);
Teng Liangf995f382017-04-04 22:09:39 +0000218 if (linkType == ndn::nfd::LINK_TYPE_NONE) {
219 linkType = forwarders.size() > 2 ? ndn::nfd::LINK_TYPE_MULTI_ACCESS :
220 ndn::nfd::LINK_TYPE_POINT_TO_POINT;
221 }
222 BOOST_ASSERT(forwarders.size() <= 2 || linkType != ndn::nfd::LINK_TYPE_POINT_TO_POINT);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700223
224 for (TopologyNode i : forwarders) {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400225 FaceUri localUri("topology://" + m_forwarders.at(i)->label + "/" + label);
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600226 auto face = makeFace(i, localUri, remoteUri, ndn::nfd::FACE_SCOPE_NON_LOCAL, linkType);
Davide Pesavento284bd622019-03-31 02:10:02 -0400227 link->addFace(i, std::move(face));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700228 }
229
230 m_links.push_back(link); // keep a shared_ptr so callers don't have to
231 return link;
232}
233
234shared_ptr<TopologyAppLink>
235TopologyTester::addAppFace(const std::string& label, TopologyNode i)
236{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400237 FaceUri localUri("topology://" + m_forwarders.at(i)->label + "/local/" + label);
238 FaceUri remoteUri("topology://" + m_forwarders.at(i)->label + "/app/" + label);
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600239 auto face = makeFace(i, localUri, remoteUri, ndn::nfd::FACE_SCOPE_LOCAL, ndn::nfd::LINK_TYPE_POINT_TO_POINT);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700240
Davide Pesavento284bd622019-03-31 02:10:02 -0400241 auto al = make_shared<TopologyAppLink>(std::move(face));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700242 m_appLinks.push_back(al); // keep a shared_ptr so callers don't have to
243 return al;
244}
245
246shared_ptr<TopologyAppLink>
247TopologyTester::addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost)
248{
249 shared_ptr<TopologyAppLink> al = this->addAppFace(label, i);
250 this->registerPrefix(i, al->getForwarderFace(), prefix, cost);
251 return al;
252}
253
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600254shared_ptr<TopologyBareLink>
255TopologyTester::addBareLink(const std::string& label, TopologyNode i, ndn::nfd::FaceScope scope,
256 ndn::nfd::LinkType linkType)
257{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400258 FaceUri localUri("topology://" + m_forwarders.at(i)->label + "/local/" + label);
259 FaceUri remoteUri("topology://" + m_forwarders.at(i)->label + "/bare/" + label);
Junxiao Shi606d5dd2019-09-23 12:47:44 -0600260 auto face = makeFace(i, localUri, remoteUri, scope, linkType);
261
262 auto bl = make_shared<TopologyBareLink>(std::move(face));
263 m_bareLinks.push_back(bl); // keep a shared_ptr so callers don't have to
264 return bl;
265}
266
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000267TopologyPcap&
268TopologyTester::getPcap(const Face& face)
269{
270 return dynamic_cast<TopologyPcapLinkService&>(*face.getLinkService());
271}
272
273void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700274TopologyTester::registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost)
275{
276 Forwarder& forwarder = this->getForwarder(i);
277 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +0000278 fib::Entry* entry = fib.insert(prefix).first;
279 fib.addOrUpdateNextHop(*entry, const_cast<Face&>(face), cost);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700280}
281
282void
Saurab Dulala6dec222019-04-01 00:15:10 -0500283TopologyTester::addEchoProducer(ndn::Face& face, const Name& prefix, time::nanoseconds replyDelay)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700284{
Saurab Dulala6dec222019-04-01 00:15:10 -0500285 BOOST_ASSERT(replyDelay >= 0_ns);
286
287 face.setInterestFilter(prefix, [=, &face] (const auto&, const auto& interest) {
288 auto data = makeData(interest.getName());
289 if (replyDelay == 0_ns) {
290 // reply immediately
291 face.put(*data);
292 }
293 else {
294 // delay the reply
295 getScheduler().schedule(replyDelay, [&face, data = std::move(data)] {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700296 face.put(*data);
297 });
Saurab Dulala6dec222019-04-01 00:15:10 -0500298 }
299 });
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700300}
301
302void
303TopologyTester::addIntervalConsumer(ndn::Face& face, const Name& prefix,
Teng Liangf995f382017-04-04 22:09:39 +0000304 time::nanoseconds interval, size_t n, int seq)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700305{
306 Name name(prefix);
Teng Liangf995f382017-04-04 22:09:39 +0000307 if (seq >= 0) {
308 name.appendSequenceNumber(seq);
309 ++seq;
310 }
311 else {
312 name.appendTimestamp();
313 }
314
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400315 auto interest = makeInterest(name);
Junxiao Shi9ede5bd2016-08-09 03:51:27 +0000316 face.expressInterest(*interest, nullptr, nullptr, nullptr);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700317
318 if (n > 1) {
Davide Pesavento3dade002019-03-19 11:29:56 -0600319 getScheduler().schedule(interval, [=, &face] {
320 addIntervalConsumer(face, prefix, interval, n - 1, seq);
321 });
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700322 }
323}
324
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400325} // namespace nfd::tests