blob: b51b001e56e2eb7587d48f8440650f63572becea [file] [log] [blame]
Junxiao Shi67ba8d22015-08-21 21:21:28 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento87fc0f82018-04-11 23:43:51 -04002/*
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -05003 * Copyright (c) 2014-2024, Regents of the University of California,
Junxiao Shi67ba8d22015-08-21 21:21:28 -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 "fw/multicast-strategy.hpp"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040027#include "common/global.hpp"
Junxiao Shi67ba8d22015-08-21 21:21:28 -070028
29#include "tests/test-common.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040030#include "tests/daemon/face/dummy-face.hpp"
Alexander Afanasyev40604e32021-02-17 12:06:26 -050031#include "choose-strategy.hpp"
Davide Pesavento3dade002019-03-19 11:29:56 -060032#include "strategy-tester.hpp"
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070033#include "topology-tester.hpp"
Junxiao Shi67ba8d22015-08-21 21:21:28 -070034
Davide Pesaventof56cf632024-01-27 22:22:06 -050035#include <boost/mp11/list.hpp>
36
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040037namespace nfd::tests {
Junxiao Shi67ba8d22015-08-21 21:21:28 -070038
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040039using MulticastStrategyTester = StrategyTester<fw::MulticastStrategy>;
Junxiao Shi890afe92016-12-15 14:34:34 +000040NFD_REGISTER_STRATEGY(MulticastStrategyTester);
41
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040042class MulticastStrategyFixture : public GlobalIoTimeFixture
Junxiao Shi890afe92016-12-15 14:34:34 +000043{
44protected:
45 MulticastStrategyFixture()
Alexander Afanasyev40604e32021-02-17 12:06:26 -050046 : strategy(choose<MulticastStrategyTester>(forwarder))
47 , face1(make_shared<DummyFace>())
Junxiao Shi890afe92016-12-15 14:34:34 +000048 , face2(make_shared<DummyFace>())
49 , face3(make_shared<DummyFace>())
50 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040051 faceTable.add(face1);
52 faceTable.add(face2);
53 faceTable.add(face3);
Junxiao Shi890afe92016-12-15 14:34:34 +000054 }
55
Davide Pesavento03a75f62021-03-09 20:38:38 -050056 bool
57 didSendInterestTo(const Face& face) const
58 {
59 auto it = std::find_if(strategy.sendInterestHistory.begin(),
60 strategy.sendInterestHistory.end(),
61 [&] (const auto& elem) { return elem.outFaceId == face.getId(); });
62 return it != strategy.sendInterestHistory.end();
63 }
64
Junxiao Shi890afe92016-12-15 14:34:34 +000065protected:
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040066 FaceTable faceTable;
67 Forwarder forwarder{faceTable};
Alexander Afanasyev40604e32021-02-17 12:06:26 -050068 MulticastStrategyTester& strategy;
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040069 Fib& fib{forwarder.getFib()};
70 Pit& pit{forwarder.getPit()};
71
Junxiao Shi890afe92016-12-15 14:34:34 +000072 shared_ptr<DummyFace> face1;
73 shared_ptr<DummyFace> face2;
74 shared_ptr<DummyFace> face3;
75};
76
Junxiao Shi5e5e4452015-09-24 16:56:52 -070077BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shi890afe92016-12-15 14:34:34 +000078BOOST_FIXTURE_TEST_SUITE(TestMulticastStrategy, MulticastStrategyFixture)
Junxiao Shi67ba8d22015-08-21 21:21:28 -070079
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070080BOOST_AUTO_TEST_CASE(Bug5123)
81{
82 fib::Entry& fibEntry = *fib.insert(Name()).first;
83 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
84
85 // Send an Interest from face 1 to face 2
Davide Pesavento03a75f62021-03-09 20:38:38 -050086 auto interest = makeInterest("ndn:/H0D6i5fc");
87 auto pitEntry = pit.insert(*interest).first;
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070088 pitEntry->insertOrUpdateInRecord(*face1, *interest);
89
Teng Liangd94b7b32022-07-10 21:29:37 +080090 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1), pitEntry);
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070091 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
Davide Pesavento03a75f62021-03-09 20:38:38 -050092 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070093
94 // Advance more than default suppression
95 this->advanceClocks(15_ms);
96
97 // Get same interest from face 2 which does not have anywhere to go
98 pitEntry = pit.insert(*interest).first;
99 pitEntry->insertOrUpdateInRecord(*face2, *interest);
100
Teng Liangd94b7b32022-07-10 21:29:37 +0800101 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face2), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500102 // Since the interest is the same as the one sent out earlier, the PIT entry should not be
103 // rejected, as any data coming back must be able to satisfy the original interest from face 1
Ashlesh Gawandec1d48372020-08-02 22:30:11 -0700104 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
105
106 /*
107 * +---------+ +---------+ +---------+
108 * | nodeA |------------| nodeB |----------| nodeC |
109 * +---------+ 10ms +---------+ 100ms +---------+
110 */
111
112 const Name PRODUCER_PREFIX = "/ndn/edu/nodeC/ping";
113
114 TopologyTester topo;
115 TopologyNode nodeA = topo.addForwarder("A"),
116 nodeB = topo.addForwarder("B"),
117 nodeC = topo.addForwarder("C");
118
119 for (TopologyNode node : {nodeA, nodeB, nodeC}) {
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400120 topo.setStrategy<fw::MulticastStrategy>(node);
Ashlesh Gawandec1d48372020-08-02 22:30:11 -0700121 }
122
123 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 10_ms, {nodeA, nodeB}),
124 linkBC = topo.addLink("BC", 100_ms, {nodeB, nodeC});
125
126 shared_ptr<TopologyAppLink> appA = topo.addAppFace("cA", nodeA),
127 appB = topo.addAppFace("cB", nodeB),
128 pingServer = topo.addAppFace("p", nodeC, PRODUCER_PREFIX);
129 topo.addEchoProducer(pingServer->getClientFace());
130 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 10);
131 topo.registerPrefix(nodeB, linkAB->getFace(nodeB), PRODUCER_PREFIX, 10);
132 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX, 100);
133
134 Name name(PRODUCER_PREFIX);
135 name.appendTimestamp();
136 interest = makeInterest(name);
137 appA->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
138
139 this->advanceClocks(10_ms, 20_ms);
140
141 // AppB expresses the same interest
142 interest->refreshNonce();
143 appB->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
144 this->advanceClocks(10_ms, 200_ms);
145
146 // Data should have made to appB
147 BOOST_CHECK_EQUAL(linkBC->getFace(nodeB).getCounters().nInData, 1);
148 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 0);
149
150 this->advanceClocks(10_ms, 10_ms);
151 // nodeA should have gotten the data successfully
152 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 1);
153 BOOST_CHECK_EQUAL(topo.getForwarder(nodeA).getCounters().nUnsolicitedData, 0);
154}
155
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700156BOOST_AUTO_TEST_CASE(Forward2)
157{
Junxiao Shia6de4292016-07-12 02:08:10 +0000158 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000159 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
160 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
161 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700162
Davide Pesavento03a75f62021-03-09 20:38:38 -0500163 auto interest = makeInterest("ndn:/H0D6i5fc");
164 auto pitEntry = pit.insert(*interest).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000165 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700166
Teng Liangd94b7b32022-07-10 21:29:37 +0800167 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3), pitEntry);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700168 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
169 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500170 BOOST_TEST(didSendInterestTo(*face1));
171 BOOST_TEST(didSendInterestTo(*face2));
Ashlesh Gawandee38e2612017-02-25 07:23:41 +0000172
Ashlesh Gawande1ef93d02022-04-08 00:25:06 -0400173 const auto TICK = time::duration_cast<time::nanoseconds>(
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400174 fw::RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL) / 10;
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700175
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000176 // downstream retransmits frequently, but the strategy should not send Interests
177 // more often than DEFAULT_MIN_RETX_INTERVAL
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -0500178 ndn::scheduler::EventId retxFrom4Evt;
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000179 size_t nSentLast = strategy.sendInterestHistory.size();
Davide Pesavento412c9822021-07-02 00:21:05 -0400180 auto timeSentLast = time::steady_clock::now();
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400181 std::function<void()> periodicalRetxFrom4; // let periodicalRetxFrom4 lambda capture itself
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000182 periodicalRetxFrom4 = [&] {
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000183 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800184 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3), pitEntry);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700185
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000186 size_t nSent = strategy.sendInterestHistory.size();
187 if (nSent > nSentLast) {
188 // Multicast strategy should multicast the interest to other two faces
189 BOOST_CHECK_EQUAL(nSent - nSentLast, 2);
Davide Pesavento3dade002019-03-19 11:29:56 -0600190 auto timeSent = time::steady_clock::now();
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000191 BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
192 nSentLast = nSent;
193 timeSentLast = timeSent;
194 }
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700195
Davide Pesavento3dade002019-03-19 11:29:56 -0600196 retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000197 };
198 periodicalRetxFrom4();
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400199 this->advanceClocks(TICK, fw::RetxSuppressionExponential::DEFAULT_MAX_INTERVAL * 16);
Davide Pesavento3dade002019-03-19 11:29:56 -0600200 retxFrom4Evt.cancel();
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700201}
202
Alexander Afanasyev4400e422021-02-17 11:17:33 -0500203BOOST_AUTO_TEST_CASE(LoopingInterest)
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700204{
Junxiao Shia6de4292016-07-12 02:08:10 +0000205 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000206 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700207
Davide Pesavento03a75f62021-03-09 20:38:38 -0500208 auto interest = makeInterest("ndn:/H0D6i5fc");
209 auto pitEntry = pit.insert(*interest).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000210 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700211
Teng Liangd94b7b32022-07-10 21:29:37 +0800212 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1), pitEntry);
Mark Theeranantachai195b78a2024-02-14 20:54:44 -0500213 BOOST_TEST(strategy.rejectPendingInterestHistory.size() == 0);
214 BOOST_TEST(strategy.sendInterestHistory.size() == 0);
215}
216
217BOOST_AUTO_TEST_CASE(DuplicateInterest)
218{
219 fib::Entry& fibEntry = *fib.insert(Name()).first;
220 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
221
222 auto interest = makeInterest("ndn:/H0D6i5fc");
223
224 // first interest
225 forwarder.onIncomingInterest(*interest, FaceEndpoint(*face1));
226 BOOST_TEST(forwarder.getCounters().nInInterests == 1);
227 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
228
229 // second interest (duplicate, should enter onInterestLoop)
230 forwarder.onIncomingInterest(*interest, FaceEndpoint(*face2));
231 BOOST_TEST(forwarder.getCounters().nInInterests == 2);
232 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
233 BOOST_TEST(strategy.rejectPendingInterestHistory.size() == 0);
234 BOOST_TEST(strategy.sendNackHistory.size() == 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700235}
236
Davide Pesavento03a75f62021-03-09 20:38:38 -0500237BOOST_AUTO_TEST_CASE(RetxSuppression)
238{
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400239 const auto suppressPeriod = fw::RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL;
Davide Pesavento03a75f62021-03-09 20:38:38 -0500240 BOOST_ASSERT(suppressPeriod >= 8_ms);
241
242 // Set up the FIB
243 fib::Entry& fibEntry = *fib.insert(Name()).first;
244 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
245 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
246 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
247
248 // Interest arrives from face 1
249 auto interest = makeInterest("/t8ZiSOi3");
250 auto pitEntry = pit.insert(*interest).first;
251 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800252 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500253
254 // forwarded to faces 2 and 3
255 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
256 BOOST_TEST(didSendInterestTo(*face2));
257 BOOST_TEST(didSendInterestTo(*face3));
258 strategy.sendInterestHistory.clear();
259
260 // still within the initial suppression period for face 2 and 3
261 this->advanceClocks(suppressPeriod - 5_ms);
262
263 // Interest arrives from face 2
264 interest->refreshNonce();
265 pitEntry = pit.insert(*interest).first;
266 pitEntry->insertOrUpdateInRecord(*face2, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800267 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face2), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500268
269 // forwarded only to face 1, suppressed on face 3
270 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
271 BOOST_TEST(didSendInterestTo(*face1));
272 strategy.sendInterestHistory.clear();
273
274 // faces 2 and 3 no longer inside the suppression window
275 this->advanceClocks(7_ms);
276
277 // Interest arrives from face 3
278 interest->refreshNonce();
279 pitEntry = pit.insert(*interest).first;
280 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800281 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500282
283 // suppressed on face 1, forwarded on face 2 (and suppression window doubles)
284 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
285 BOOST_TEST(didSendInterestTo(*face2));
286 strategy.sendInterestHistory.clear();
287
288 // face 1 exits the suppression period, face 2 still inside
289 this->advanceClocks(2 * suppressPeriod - 2_ms);
290
291 // Interest arrives from face 3
292 interest->refreshNonce();
293 pitEntry = pit.insert(*interest).first;
294 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800295 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500296
297 // forwarded only to face 1, suppressed on face 2
298 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
299 BOOST_TEST(didSendInterestTo(*face1));
300 strategy.sendInterestHistory.clear();
301
302 // face 2 exits the suppression period
303 this->advanceClocks(3_ms);
304
305 // Interest arrives from face 1
306 interest->refreshNonce();
307 pitEntry = pit.insert(*interest).first;
308 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800309 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500310
311 // forwarded to faces 2 and 3
312 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
313 BOOST_TEST(didSendInterestTo(*face2));
314 BOOST_TEST(didSendInterestTo(*face3));
315 strategy.sendInterestHistory.clear();
316}
317
318BOOST_AUTO_TEST_CASE(NewNextHop)
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500319{
320 fib::Entry& fibEntry = *fib.insert(Name()).first;
321 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
322 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
323
Davide Pesavento03a75f62021-03-09 20:38:38 -0500324 auto interest = makeInterest("ndn:/H0D6i5fc");
325 auto pitEntry = pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500326 pitEntry->insertOrUpdateInRecord(*face1, *interest);
327
Teng Liangd94b7b32022-07-10 21:29:37 +0800328 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500329 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
330 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);
331
332 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
333 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
334 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
335}
336
337BOOST_AUTO_TEST_SUITE(LocalhopScope)
338
339class ForwardAsyncFixture : public MulticastStrategyFixture
340{
341protected:
342 shared_ptr<Face> inFace1;
343 shared_ptr<Face> inFace2;
344 shared_ptr<Face> fibFace1;
345 shared_ptr<Face> fibFace2;
346 shared_ptr<Face> newFibFace;
347
348 size_t expectedInterests = 0;
349};
350
351class BasicNonLocal : public ForwardAsyncFixture
352{
353protected:
354 BasicNonLocal()
355 {
356 inFace1 = face1;
357 // inFace2 = nullptr;
358 fibFace1 = face1;
359 fibFace2 = face2;
360 newFibFace = face3;
361 expectedInterests = 0; // anything received on non-local face can only be sent to local face
362 }
363};
364
365class NewFibLocal : public ForwardAsyncFixture
366{
367protected:
368 NewFibLocal()
369 {
370 inFace1 = face1;
371 // inFace2 = nullptr;
372 fibFace1 = face1;
373 fibFace2 = face2;
374 newFibFace = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
375 expectedInterests = 1;
376
377 faceTable.add(newFibFace);
378 }
379};
380
381class InFaceLocal : public ForwardAsyncFixture
382{
383protected:
384 InFaceLocal()
385 {
386 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
387 // inFace2 = nullptr;
388 fibFace1 = face1;
389 fibFace2 = face2;
390 newFibFace = face3;
391 expectedInterests = 1;
392
393 faceTable.add(inFace1);
394 }
395};
396
397class InFaceLocalSameNewFace : public ForwardAsyncFixture
398{
399protected:
400 InFaceLocalSameNewFace()
401 {
402 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
403 // inFace2 = nullptr;
404 fibFace1 = face1;
405 fibFace2 = face2;
406 newFibFace = inFace1;
407 expectedInterests = 0;
408
409 faceTable.add(inFace1);
410 }
411};
412
413class InFaceLocalAdHocSameNewFace : public ForwardAsyncFixture
414{
415protected:
416 InFaceLocalAdHocSameNewFace()
417 {
418 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL,
419 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
420 ndn::nfd::LINK_TYPE_AD_HOC);
421 // inFace2 = nullptr;
422 fibFace1 = face1;
423 fibFace2 = face2;
424 newFibFace = inFace1;
425 expectedInterests = 1;
426
427 faceTable.add(inFace1);
428 }
429};
430
431class InFaceLocalAndNonLocal1 : public ForwardAsyncFixture
432{
433protected:
434 InFaceLocalAndNonLocal1()
435 {
436 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
437 inFace2 = face1;
438 fibFace1 = face1;
439 fibFace2 = face2;
440 newFibFace = face3;
441 expectedInterests = 1;
442
443 faceTable.add(inFace1);
444 }
445};
446
447class InFaceLocalAndNonLocal2 : public ForwardAsyncFixture
448{
449protected:
450 InFaceLocalAndNonLocal2()
451 {
452 inFace1 = face1;
453 inFace2 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
454 fibFace1 = face1;
455 fibFace2 = face2;
456 newFibFace = face3;
457 expectedInterests = 1;
458
459 faceTable.add(inFace2);
460 }
461};
462
463class InFaceSelection1 : public ForwardAsyncFixture
464{
465protected:
466 InFaceSelection1()
467 {
468 inFace1 = face1;
469 // inFace2 = nullptr;
470 fibFace1 = face3;
471 fibFace2 = face2;
472 newFibFace = face1;
473
474 expectedInterests = 0;
475 }
476};
477
478class InFaceSelection2 : public ForwardAsyncFixture
479{
480protected:
481 InFaceSelection2()
482 {
483 inFace1 = face2;
484 inFace2 = face1;
485 fibFace1 = face2;
486 fibFace2 = face3;
487 newFibFace = face1;
488
489 // this test will trigger the check for additional branch, but it
490 // still is not going to pass the localhop check
491 expectedInterests = 0;
492 }
493};
494
Davide Pesaventof56cf632024-01-27 22:22:06 -0500495using Tests = boost::mp11::mp_list<
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500496 BasicNonLocal,
497 NewFibLocal,
498 InFaceLocal,
499 InFaceLocalSameNewFace,
500 InFaceLocalAdHocSameNewFace,
501 InFaceLocalAndNonLocal1,
502 InFaceLocalAndNonLocal2,
503 InFaceSelection1,
504 InFaceSelection2
505>;
506
507BOOST_FIXTURE_TEST_CASE_TEMPLATE(ForwardAsync, T, Tests, T)
508{
509 fib::Entry& fibEntry = *this->fib.insert(Name("/localhop")).first;
510 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace1, 0);
511 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace2, 0);
512
Davide Pesavento03a75f62021-03-09 20:38:38 -0500513 auto interest = makeInterest("ndn:/localhop/H0D6i5fc");
514 auto pitEntry = this->pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500515 pitEntry->insertOrUpdateInRecord(*this->inFace1, *interest);
Teng Liangd94b7b32022-07-10 21:29:37 +0800516 this->strategy.afterReceiveInterest(*interest, FaceEndpoint(*this->inFace1), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500517
518 if (this->inFace2 != nullptr) {
Davide Pesavento03a75f62021-03-09 20:38:38 -0500519 auto interest2 = makeInterest("ndn:/localhop/H0D6i5fc");
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500520 pitEntry->insertOrUpdateInRecord(*this->inFace2, *interest2);
Teng Liangd94b7b32022-07-10 21:29:37 +0800521 this->strategy.afterReceiveInterest(*interest2, FaceEndpoint(*this->inFace2), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500522 }
523
524 this->strategy.sendInterestHistory.clear();
525 this->fib.addOrUpdateNextHop(fibEntry, *this->newFibFace, 0);
526 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), this->expectedInterests);
527}
528
529BOOST_AUTO_TEST_SUITE_END() // LocalhopScope
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700530BOOST_AUTO_TEST_SUITE_END() // TestMulticastStrategy
531BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700532
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400533} // namespace nfd::tests