blob: 78eb79530dd5cacf8c4bdfdd7fc411574e08d79f [file] [log] [blame]
Vince Lehman8a4c29e2016-07-11 08:49:35 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -05002/*
Saurab Dulal432be572021-01-26 12:09:29 -06003 * Copyright (c) 2014-2021, Regents of the University of California,
Vince Lehman8a4c29e2016-07-11 08:49:35 +00004 * 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/asf-strategy.hpp"
27
Junxiao Shi890afe92016-12-15 14:34:34 +000028#include "strategy-tester.hpp"
Vince Lehman8a4c29e2016-07-11 08:49:35 +000029#include "topology-tester.hpp"
30
31namespace nfd {
32namespace fw {
33namespace asf {
34namespace tests {
35
36using namespace nfd::fw::tests;
37
Junxiao Shi890afe92016-12-15 14:34:34 +000038// The tester is unused in this file, but it's used in various templated test suites.
Davide Pesavento14e71f02019-03-28 17:35:25 -040039using AsfStrategyTester = StrategyTester<AsfStrategy>;
Junxiao Shi890afe92016-12-15 14:34:34 +000040NFD_REGISTER_STRATEGY(AsfStrategyTester);
41
Vince Lehman8a4c29e2016-07-11 08:49:35 +000042BOOST_AUTO_TEST_SUITE(Fw)
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040043BOOST_FIXTURE_TEST_SUITE(TestAsfStrategy, GlobalIoTimeFixture)
Vince Lehman8a4c29e2016-07-11 08:49:35 +000044
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040045class AsfGridFixture : public GlobalIoTimeFixture
Vince Lehman8a4c29e2016-07-11 08:49:35 +000046{
47protected:
Davide Pesavento14e71f02019-03-28 17:35:25 -040048 explicit
Saurab Dulal432be572021-01-26 12:09:29 -060049 AsfGridFixture(const Name& params = AsfStrategy::getStrategyName(),
50 time::nanoseconds replyDelay = 0_ns)
Davide Pesavento14e71f02019-03-28 17:35:25 -040051 : parameters(params)
Vince Lehman8a4c29e2016-07-11 08:49:35 +000052 {
53 /*
54 * +---------+
55 * +----->| nodeB |<------+
56 * | +---------+ |
57 * 10ms | | 10ms
58 * v v
59 * +---------+ +---------+
60 * | nodeA | | nodeC |
61 * +---------+ +---------+
62 * ^ ^
63 * 100ms | | 100ms
64 * | +---------+ |
65 * +----->| nodeD |<------+
66 * +---------+
67 */
68
69 nodeA = topo.addForwarder("A");
70 nodeB = topo.addForwarder("B");
71 nodeC = topo.addForwarder("C");
72 nodeD = topo.addForwarder("D");
73
Saurab Dulal432be572021-01-26 12:09:29 -060074 topo.setStrategy<AsfStrategy>(nodeA, Name("/"), parameters);
75 topo.setStrategy<AsfStrategy>(nodeB, Name("/"), parameters);
76 topo.setStrategy<AsfStrategy>(nodeC, Name("/"), parameters);
77 topo.setStrategy<AsfStrategy>(nodeD, Name("/"), parameters);
Vince Lehman8a4c29e2016-07-11 08:49:35 +000078
Davide Pesavento14e71f02019-03-28 17:35:25 -040079 linkAB = topo.addLink("AB", 10_ms, {nodeA, nodeB});
80 linkAD = topo.addLink("AD", 100_ms, {nodeA, nodeD});
81 linkBC = topo.addLink("BC", 10_ms, {nodeB, nodeC});
82 linkCD = topo.addLink("CD", 100_ms, {nodeC, nodeD});
Vince Lehman8a4c29e2016-07-11 08:49:35 +000083
84 consumer = topo.addAppFace("c", nodeA);
85 producer = topo.addAppFace("p", nodeC, PRODUCER_PREFIX);
Saurab Dulala6dec222019-04-01 00:15:10 -050086
87 topo.addEchoProducer(producer->getClientFace(), PRODUCER_PREFIX, replyDelay);
Vince Lehman8a4c29e2016-07-11 08:49:35 +000088
89 // Register producer prefix on consumer node
90 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 10);
91 topo.registerPrefix(nodeA, linkAD->getFace(nodeA), PRODUCER_PREFIX, 5);
92 }
93
94 void
Saurab Dulal432be572021-01-26 12:09:29 -060095 runConsumer(size_t numInterests = 30)
Vince Lehman8a4c29e2016-07-11 08:49:35 +000096 {
Davide Pesavento14e71f02019-03-28 17:35:25 -040097 topo.addIntervalConsumer(consumer->getClientFace(), PRODUCER_PREFIX, 1_s, numInterests);
98 this->advanceClocks(10_ms, time::seconds(numInterests));
Vince Lehman8a4c29e2016-07-11 08:49:35 +000099 }
100
101protected:
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500102 Name parameters;
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000103 TopologyTester topo;
104
105 TopologyNode nodeA;
106 TopologyNode nodeB;
107 TopologyNode nodeC;
108 TopologyNode nodeD;
109
110 shared_ptr<TopologyLink> linkAB;
111 shared_ptr<TopologyLink> linkAD;
112 shared_ptr<TopologyLink> linkBC;
113 shared_ptr<TopologyLink> linkCD;
114
115 shared_ptr<TopologyAppLink> consumer;
116 shared_ptr<TopologyAppLink> producer;
117
118 static const Name PRODUCER_PREFIX;
119};
120
Saurab Dulal432be572021-01-26 12:09:29 -0600121const Name AsfGridFixture::PRODUCER_PREFIX("/hr/C");
122
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500123class AsfStrategyParametersGridFixture : public AsfGridFixture
124{
125protected:
126 AsfStrategyParametersGridFixture()
127 : AsfGridFixture(Name(AsfStrategy::getStrategyName())
128 .append("probing-interval~30000")
129 .append("n-silent-timeouts~5"))
130 {
131 }
132};
133
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000134BOOST_FIXTURE_TEST_CASE(Basic, AsfGridFixture)
135{
136 // Both nodeB and nodeD have FIB entries to reach the producer
137 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
138 topo.registerPrefix(nodeD, linkCD->getFace(nodeD), PRODUCER_PREFIX);
139
140 runConsumer();
141
142 // ASF should use the Face to nodeD because it has lower routing cost.
143 // After 5 seconds, a probe Interest should be sent to the Face to nodeB,
144 // and the probe should return Data quicker. ASF should then use the Face
145 // to nodeB to forward the remaining Interests.
146 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 30);
Alex Lane9cec6992020-03-05 19:10:09 -0600147 // Because of exploration, will forward to AB and AD simultaneously at least once
148 BOOST_CHECK_GE(linkAB->getFace(nodeA).getCounters().nOutInterests, 25);
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000149 BOOST_CHECK_LE(linkAD->getFace(nodeA).getCounters().nOutInterests, 6);
150
151 // If the link from nodeA to nodeB fails, ASF should start using the Face
152 // to nodeD again.
153 linkAB->fail();
154
155 runConsumer();
Alex Lane9cec6992020-03-05 19:10:09 -0600156 // We experience 3 silent timeouts before marking AB as timed out on the fourth interest.
157 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 56);
158 BOOST_CHECK_LE(linkAB->getFace(nodeA).getCounters().nOutInterests, 36);
159 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 24);
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000160
161 // If the link from nodeA to nodeB recovers, ASF should probe the Face
162 // to nodeB and start using it again.
163 linkAB->recover();
164
165 // Advance time to ensure probing is due
Davide Pesavento14e71f02019-03-28 17:35:25 -0400166 this->advanceClocks(10_ms, 10_s);
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000167
168 runConsumer();
Alex Lane9cec6992020-03-05 19:10:09 -0600169 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 86);
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000170 BOOST_CHECK_GE(linkAB->getFace(nodeA).getCounters().nOutInterests, 50);
171 BOOST_CHECK_LE(linkAD->getFace(nodeA).getCounters().nOutInterests, 40);
172
173 // If both links fail, nodeA should forward to the next hop with the lowest cost
174 linkAB->fail();
175 linkAD->fail();
176
177 runConsumer();
178
Alex Lane9cec6992020-03-05 19:10:09 -0600179 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 86);
180 BOOST_CHECK_LE(linkAB->getFace(nodeA).getCounters().nOutInterests, 65); // FIXME #3830
181 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 57); // FIXME #3830
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000182}
183
184BOOST_FIXTURE_TEST_CASE(Nack, AsfGridFixture)
185{
186 // nodeB has a FIB entry to reach the producer, but nodeD does not
187 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
188
189 // The strategy should first try to send to nodeD. But since nodeD does not have a route for
190 // the producer's prefix, it should return a NO_ROUTE Nack. The strategy should then start using the Face to
191 // nodeB.
192 runConsumer();
193
194 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nInNacks, 1);
195 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 29);
196 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nOutInterests, 29);
197
198 // nodeD should receive 2 Interests: one for the very first Interest and
199 // another from a probe
200 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 2);
201}
202
Saurab Dulala6dec222019-04-01 00:15:10 -0500203class AsfStrategyDelayedDataFixture : public AsfGridFixture
204{
205protected:
206 AsfStrategyDelayedDataFixture()
207 : AsfGridFixture(Name(AsfStrategy::getStrategyName()), 400_ms)
208 {
209 }
210};
211
212BOOST_FIXTURE_TEST_CASE(InterestForwarding, AsfStrategyDelayedDataFixture)
213{
Saurab Dulala6dec222019-04-01 00:15:10 -0500214 Name name(PRODUCER_PREFIX);
215 name.appendTimestamp();
Saurab Dulal432be572021-01-26 12:09:29 -0600216 auto interest = makeInterest(name);
Saurab Dulala6dec222019-04-01 00:15:10 -0500217
218 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
219 topo.registerPrefix(nodeD, linkCD->getFace(nodeD), PRODUCER_PREFIX);
220
221 // The first interest should go via link AD
222 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
223 this->advanceClocks(10_ms, 100_ms);
224 BOOST_CHECK_EQUAL(linkAD->getFace(nodeA).getCounters().nOutInterests, 1);
225
226 // Second interest should go via link AB
227 interest->refreshNonce();
228 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
229 this->advanceClocks(10_ms, 100_ms);
230 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nOutInterests, 1);
231
232 // The third interest should again go via AD, since both the face from A is already used
233 // and so asf should choose the earliest used face i.e. AD
234 interest->refreshNonce();
235 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
236 this->advanceClocks(10_ms, 100_ms);
237 BOOST_CHECK_EQUAL(linkAD->getFace(nodeA).getCounters().nOutInterests, 2);
238
239 this->advanceClocks(time::milliseconds(500), time::seconds(5));
240 BOOST_CHECK_EQUAL(linkAD->getFace(nodeA).getCounters().nInData, 1);
241 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 1);
242 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 1);
Saurab Dulala6dec222019-04-01 00:15:10 -0500243}
244
Saurab Dulal432be572021-01-26 12:09:29 -0600245BOOST_AUTO_TEST_CASE(Retransmission) // Bug #4874
Saurab Dulala6dec222019-04-01 00:15:10 -0500246{
Saurab Dulala6dec222019-04-01 00:15:10 -0500247 // Avoid clearing pit entry for those incoming interest that have pit entry but no next hops
Saurab Dulal432be572021-01-26 12:09:29 -0600248 /*
249 * +---------+ 10ms +---------+
250 * | nodeB | ------> | nodeC |
251 * +---------+ +---------+
252 */
Saurab Dulala6dec222019-04-01 00:15:10 -0500253
Saurab Dulal432be572021-01-26 12:09:29 -0600254 const Name PRODUCER_PREFIX = "/pnr/C";
Saurab Dulala6dec222019-04-01 00:15:10 -0500255 TopologyTester topo;
256
257 TopologyNode nodeB = topo.addForwarder("B"),
258 nodeC = topo.addForwarder("C");
259
Saurab Dulal432be572021-01-26 12:09:29 -0600260 for (auto node : {nodeB, nodeC}) {
261 topo.setStrategy<AsfStrategy>(node);
262 }
Saurab Dulala6dec222019-04-01 00:15:10 -0500263
Saurab Dulal432be572021-01-26 12:09:29 -0600264 auto linkBC = topo.addLink("BC", time::milliseconds(10), {nodeB, nodeC});
Saurab Dulala6dec222019-04-01 00:15:10 -0500265
Saurab Dulal432be572021-01-26 12:09:29 -0600266 auto consumer = topo.addAppFace("c", nodeB),
267 producer = topo.addAppFace("p", nodeC, PRODUCER_PREFIX);
Saurab Dulala6dec222019-04-01 00:15:10 -0500268
269 topo.addEchoProducer(producer->getClientFace(), PRODUCER_PREFIX, 100_ms);
270
271 Name name(PRODUCER_PREFIX);
272 name.appendTimestamp();
Saurab Dulal432be572021-01-26 12:09:29 -0600273 auto interest = makeInterest(name);
Saurab Dulala6dec222019-04-01 00:15:10 -0500274
Saurab Dulal432be572021-01-26 12:09:29 -0600275 auto& pit = topo.getForwarder(nodeB).getPit();
276 auto pitEntry = pit.insert(*interest).first;
Saurab Dulala6dec222019-04-01 00:15:10 -0500277
Teng Liangebc20f62020-06-23 16:55:20 -0700278 topo.getForwarder(nodeB).onOutgoingInterest(pitEntry, linkBC->getFace(nodeB), *interest);
Saurab Dulala6dec222019-04-01 00:15:10 -0500279 this->advanceClocks(time::milliseconds(100));
280
281 interest->refreshNonce();
282 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
283 this->advanceClocks(time::milliseconds(100));
284
Saurab Dulal432be572021-01-26 12:09:29 -0600285 auto outRecord = pitEntry->getOutRecord(linkBC->getFace(nodeB));
Saurab Dulala6dec222019-04-01 00:15:10 -0500286 BOOST_CHECK(outRecord != pitEntry->out_end());
287
288 this->advanceClocks(time::milliseconds(100));
289 BOOST_CHECK_EQUAL(linkBC->getFace(nodeC).getCounters().nOutData, 1);
290 BOOST_CHECK_EQUAL(linkBC->getFace(nodeB).getCounters().nInData, 1);
291}
292
Saurab Dulal432be572021-01-26 12:09:29 -0600293BOOST_AUTO_TEST_CASE(PerUpstreamSuppression)
294{
295 /*
296 * +---------+
297 * +----| nodeB |----+
298 * | +---------+ |
299 * 50ms | | 50ms
300 * | |
301 * +---------+ 50ms +---------+
302 * | nodeA | <-----> | nodeP |
303 * +---------+ +---------+
304 */
305
306 const Name PRODUCER_PREFIX = "/suppress/me";
307 TopologyTester topo;
308
309 TopologyNode nodeA = topo.addForwarder("A"),
310 nodeB = topo.addForwarder("B"),
311 nodeP = topo.addForwarder("P");
312
313 for (auto node : {nodeA, nodeB, nodeP}) {
314 topo.setStrategy<AsfStrategy>(node);
315 }
316
317 auto linkAB = topo.addLink("AB", 50_ms, {nodeA, nodeB});
318 auto linkAP = topo.addLink("AP", 50_ms, {nodeA, nodeP});
319 auto linkBP = topo.addLink("BP", 50_ms, {nodeB, nodeP});
320
321 auto consumer = topo.addAppFace("cons", nodeA),
322 producer = topo.addAppFace("prod", nodeP, PRODUCER_PREFIX);
323
324 topo.addEchoProducer(producer->getClientFace(), PRODUCER_PREFIX);
325
326 topo.registerPrefix(nodeA, linkAP->getFace(nodeA), PRODUCER_PREFIX, 10);
327 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 1);
328 topo.registerPrefix(nodeB, linkBP->getFace(nodeB), PRODUCER_PREFIX, 1);
329
330 auto& faceA2B = linkAB->getFace(nodeA);
331 auto& faceA2P = linkAP->getFace(nodeA);
332
333 Name name(PRODUCER_PREFIX);
334 name.appendTimestamp();
335 // very short lifetime to make it expire within the initial retx suppression period (10ms)
336 auto interest = makeInterest(name, false, 5_ms);
337
338 // 1st interest should be sent to B
339 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
340 this->advanceClocks(1_ms);
341 BOOST_TEST(faceA2B.getCounters().nOutInterests == 1);
342 BOOST_TEST(faceA2P.getCounters().nOutInterests == 0);
343
344 // 2nd interest should be sent to P and NOT suppressed
345 interest->setInterestLifetime(100_ms);
346 interest->refreshNonce();
347 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
348 this->advanceClocks(1_ms);
349 BOOST_TEST(faceA2B.getCounters().nOutInterests == 1);
350 BOOST_TEST(faceA2P.getCounters().nOutInterests == 1);
351
352 this->advanceClocks(1_ms);
353
354 // 3rd interest should be suppressed
355 // without suppression, it would have been sent again to B as that's the earliest out-record
356 interest->refreshNonce();
357 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
358 this->advanceClocks(1_ms);
359 BOOST_TEST(faceA2B.getCounters().nOutInterests == 1);
360 BOOST_TEST(faceA2P.getCounters().nOutInterests == 1);
361
362 this->advanceClocks(2_ms); // 1st interest should expire now
363
364 // 4th interest should be suppressed
365 // without suppression, it would have been sent again to B because the out-record expired
366 interest->refreshNonce();
367 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
368 this->advanceClocks(1_ms);
369 BOOST_TEST(faceA2B.getCounters().nOutInterests == 1);
370 BOOST_TEST(faceA2P.getCounters().nOutInterests == 1);
371
372 this->advanceClocks(5_ms); // suppression window ends
373
374 // 5th interest is sent to B and is outside the suppression window
375 interest->refreshNonce();
376 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
377 this->advanceClocks(1_ms);
378 BOOST_TEST(faceA2B.getCounters().nOutInterests == 2);
379 BOOST_TEST(faceA2P.getCounters().nOutInterests == 1);
380
381 this->advanceClocks(10_ms);
382
383 // 6th interest is sent to P and is outside the suppression window
384 interest->refreshNonce();
385 consumer->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
386 this->advanceClocks(1_ms);
387 BOOST_TEST(faceA2B.getCounters().nOutInterests == 2);
388 BOOST_TEST(faceA2P.getCounters().nOutInterests == 2);
389}
390
Ashlesh Gawande2a73f352016-12-01 15:37:03 +0000391BOOST_AUTO_TEST_CASE(NoPitOutRecordAndProbeInterestNewNonce)
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600392{
Saurab Dulal432be572021-01-26 12:09:29 -0600393 /* +---------+
394 * | nodeD |
395 * +---------+
396 * |
397 * | 80ms
398 * |
399 * |
400 * +---------+
401 * +----->| nodeB |<------+
402 * | +---------+ |
403 * 15ms | | 16ms
404 * v v
405 * +---------+ +---------+
406 * | nodeA |--------------| nodeC |
407 * +---------+ 14ms +---------+
408 */
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600409
410 const Name PRODUCER_PREFIX = "/ndn/edu/nodeD/ping";
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600411 TopologyTester topo;
Saurab Dulal432be572021-01-26 12:09:29 -0600412
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600413 TopologyNode nodeA = topo.addForwarder("A"),
414 nodeB = topo.addForwarder("B"),
415 nodeC = topo.addForwarder("C"),
416 nodeD = topo.addForwarder("D");
417
Saurab Dulal432be572021-01-26 12:09:29 -0600418 for (auto node : {nodeA, nodeB, nodeC, nodeD}) {
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500419 topo.setStrategy<AsfStrategy>(node);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600420 }
421
Saurab Dulal432be572021-01-26 12:09:29 -0600422 auto linkAB = topo.addLink("AB", 15_ms, {nodeA, nodeB}),
423 linkAC = topo.addLink("AC", 14_ms, {nodeA, nodeC}),
424 linkBC = topo.addLink("BC", 16_ms, {nodeB, nodeC}),
425 linkBD = topo.addLink("BD", 80_ms, {nodeB, nodeD});
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600426
Saurab Dulal432be572021-01-26 12:09:29 -0600427 auto ping = topo.addAppFace("c", nodeA);
428 auto pingServer = topo.addAppFace("p", nodeD, PRODUCER_PREFIX);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600429 topo.addEchoProducer(pingServer->getClientFace());
430
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600431 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 15);
432 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), PRODUCER_PREFIX, 14);
433 topo.registerPrefix(nodeC, linkBC->getFace(nodeC), PRODUCER_PREFIX, 16);
434 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), PRODUCER_PREFIX, 80);
435
436 // Send 6 interest since probes can be scheduled b/w 0-5 seconds
437 for (int i = 1; i < 7; i++) {
438 // Send ping number i
439 Name name(PRODUCER_PREFIX);
440 name.appendTimestamp();
Davide Pesavento51cf75c2020-03-11 22:21:13 -0400441 auto interest = makeInterest(name);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600442 ping->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
Davide Pesavento51cf75c2020-03-11 22:21:13 -0400443 auto nonce = interest->getNonce();
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600444
445 // Don't know when the probe will be triggered since it is random between 0-5 seconds
446 // or whether it will be triggered for this interest
Davide Pesavento14e71f02019-03-28 17:35:25 -0400447 for (int j = 1; j <= 1000 && linkAB->getFace(nodeA).getCounters().nOutInterests != 1; ++j) {
448 this->advanceClocks(1_ms);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600449 }
450
451 // Check if probe is sent to B else send another ping
452 if (linkAB->getFace(nodeA).getCounters().nOutInterests == 1) {
Ashlesh Gawande2a73f352016-12-01 15:37:03 +0000453 // Get pitEntry of node A
Davide Pesavento51cf75c2020-03-11 22:21:13 -0400454 auto pitEntry = topo.getForwarder(nodeA).getPit().find(*interest);
455 // Get outRecord associated with face towards B
456 auto outRecord = pitEntry->getOutRecord(linkAB->getFace(nodeA));
457 BOOST_REQUIRE(outRecord != pitEntry->out_end());
Ashlesh Gawande2a73f352016-12-01 15:37:03 +0000458
Davide Pesavento51cf75c2020-03-11 22:21:13 -0400459 // Check that Nonce of interest is not equal to Nonce of Probe
Ashlesh Gawande2a73f352016-12-01 15:37:03 +0000460 BOOST_CHECK_NE(nonce, outRecord->getLastNonce());
461
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600462 // B should not have received the probe interest yet
463 BOOST_CHECK_EQUAL(linkAB->getFace(nodeB).getCounters().nInInterests, 0);
464
465 // i-1 interests through B when no probe
466 BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nOutInterests, i - 1);
467
468 // After 15ms, B should get the probe interest
Davide Pesavento14e71f02019-03-28 17:35:25 -0400469 this->advanceClocks(1_ms, 15_ms);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600470 BOOST_CHECK_EQUAL(linkAB->getFace(nodeB).getCounters().nInInterests, 1);
471 BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nOutInterests, i);
472
Ashlesh Gawande2a73f352016-12-01 15:37:03 +0000473 pitEntry = topo.getForwarder(nodeB).getPit().find(*interest);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600474
475 // Get outRecord associated with face towards D.
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000476 outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600477 BOOST_CHECK(outRecord != pitEntry->out_end());
478
479 // RTT between B and D
Davide Pesavento14e71f02019-03-28 17:35:25 -0400480 this->advanceClocks(5_ms, 160_ms);
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000481 outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600482
483 BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nInData, i);
484
485 BOOST_CHECK(outRecord == pitEntry->out_end());
486
487 // Data is returned for the ping after 15 ms - will result in false measurement
488 // 14+16-15 = 15ms
489 // Since outRecord == pitEntry->out_end()
Davide Pesavento14e71f02019-03-28 17:35:25 -0400490 this->advanceClocks(1_ms, 15_ms);
Ashlesh Gawanded3ac7772016-11-06 00:53:05 -0600491 BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nInData, i+1);
492
493 break;
494 }
495 }
496}
497
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500498BOOST_FIXTURE_TEST_CASE(IgnoreTimeouts, AsfStrategyParametersGridFixture)
499{
500 // Both nodeB and nodeD have FIB entries to reach the producer
501 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
502 topo.registerPrefix(nodeD, linkCD->getFace(nodeD), PRODUCER_PREFIX);
503
504 // Send 15 interests let it change to use the 10 ms link
505 runConsumer(15);
506
Saurab Dulal432be572021-01-26 12:09:29 -0600507 uint64_t outInterestsBeforeFailure = linkAD->getFace(nodeA).getCounters().nOutInterests;
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500508
509 // Bring down 10 ms link
510 linkAB->fail();
511
512 // Send 6 interests, first 5 will be ignored and on the 6th it will record the timeout
513 // ready to switch for the next interest
514 runConsumer(6);
515
516 // Check that link has not been switched to 100 ms because n-silent-timeouts = 5
Saurab Dulal432be572021-01-26 12:09:29 -0600517 BOOST_CHECK_EQUAL(linkAD->getFace(nodeA).getCounters().nOutInterests, outInterestsBeforeFailure);
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500518
519 // Send 5 interests, check that 100 ms link is used
520 runConsumer(5);
521
Saurab Dulal432be572021-01-26 12:09:29 -0600522 BOOST_CHECK_EQUAL(linkAD->getFace(nodeA).getCounters().nOutInterests, outInterestsBeforeFailure + 5);
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500523}
524
525BOOST_FIXTURE_TEST_CASE(ProbingInterval, AsfStrategyParametersGridFixture)
526{
527 // Both nodeB and nodeD have FIB entries to reach the producer
528 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
529 topo.registerPrefix(nodeD, linkCD->getFace(nodeD), PRODUCER_PREFIX);
530
531 // Send 6 interests let it change to use the 10 ms link
532 runConsumer(6);
533
Saurab Dulal432be572021-01-26 12:09:29 -0600534 auto linkAC = topo.addLink("AC", 5_ms, {nodeA, nodeD});
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500535 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), PRODUCER_PREFIX, 1);
536
537 BOOST_CHECK_EQUAL(linkAC->getFace(nodeA).getCounters().nOutInterests, 0);
538
539 // After 30 seconds a probe would be sent that would switch make ASF switch
540 runConsumer(30);
541
542 BOOST_CHECK_EQUAL(linkAC->getFace(nodeA).getCounters().nOutInterests, 1);
543}
544
Saurab Dulal432be572021-01-26 12:09:29 -0600545BOOST_AUTO_TEST_CASE(InstantiationWithParameters)
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500546{
Saurab Dulal432be572021-01-26 12:09:29 -0600547 FaceTable faceTable;
548 Forwarder forwarder{faceTable};
549
550 auto checkValidity = [&] (std::string parameters, bool isCorrect) {
551 Name strategyName(Name(AsfStrategy::getStrategyName()).append(std::move(parameters)));
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500552 if (isCorrect) {
553 BOOST_CHECK_NO_THROW(make_unique<AsfStrategy>(forwarder, strategyName));
554 }
555 else {
556 BOOST_CHECK_THROW(make_unique<AsfStrategy>(forwarder, strategyName), std::invalid_argument);
557 }
Saurab Dulal432be572021-01-26 12:09:29 -0600558 };
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500559
Ashlesh Gawande92e4ea52017-07-19 11:38:12 -0500560 checkValidity("/probing-interval~30000/n-silent-timeouts~5", true);
561 checkValidity("/n-silent-timeouts~5/probing-interval~30000", true);
562 checkValidity("/probing-interval~30000", true);
563 checkValidity("/n-silent-timeouts~5", true);
564 checkValidity("", true);
565
566 checkValidity("/probing-interval~500", false); // At least 1 seconds
567 checkValidity("/probing-interval~-5000", false);
568 checkValidity("/n-silent-timeouts~-5", false);
569 checkValidity("/n-silent-timeouts~-5/probing-interval~-30000", false);
570 checkValidity("/n-silent-timeouts", false);
571 checkValidity("/probing-interval~", false);
572 checkValidity("/~1000", false);
573 checkValidity("/probing-interval~foo", false);
574 checkValidity("/n-silent-timeouts~1~2", false);
575}
576
Vince Lehman8a4c29e2016-07-11 08:49:35 +0000577BOOST_AUTO_TEST_SUITE_END() // TestAsfStrategy
578BOOST_AUTO_TEST_SUITE_END() // Fw
579
580} // namespace tests
581} // namespace asf
582} // namespace fw
583} // namespace nfd