blob: 5467c4ae4a24697c22df03c2d52e28fadbaf4256 [file] [log] [blame]
Teng Liang7003e0b2018-03-03 16:03:30 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
ashiqopud3ae85d2019-02-17 02:29:55 +00003 * Copyright (c) 2014-2019, Regents of the University of California,
Teng Liang7003e0b2018-03-03 16:03:30 -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
Teng Liang7003e0b2018-03-03 16:03:30 -070026#include "tests/test-common.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040027#include "tests/daemon/global-io-fixture.hpp"
28#include "tests/daemon/face/dummy-face.hpp"
29#include "choose-strategy.hpp"
30#include "dummy-strategy.hpp"
Teng Liang7003e0b2018-03-03 16:03:30 -070031
Teng Liang85a36632018-03-21 05:59:34 -070032#include <ndn-cxx/lp/tags.hpp>
33
Teng Liang7003e0b2018-03-03 16:03:30 -070034namespace nfd {
35namespace fw {
36namespace tests {
37
38using namespace nfd::tests;
39
40BOOST_AUTO_TEST_SUITE(Fw)
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040041BOOST_FIXTURE_TEST_SUITE(TestPitExpiry, GlobalIoTimeFixture)
Teng Liang7003e0b2018-03-03 16:03:30 -070042
43class PitExpiryTestStrategy : public DummyStrategy
44{
45public:
46 static Name
47 getStrategyName(uint64_t version)
48 {
49 return Name("/PitExpiryTestStrategy").appendVersion(version);
50 }
51
52 static void
53 registerAs(const Name& strategyName)
54 {
55 registerAsImpl<PitExpiryTestStrategy>(strategyName);
56 }
57
58 explicit
59 PitExpiryTestStrategy(Forwarder& forwarder, const Name& name = getStrategyName(1))
60 : DummyStrategy(forwarder, name)
61 {
62 }
63
64 void
ashiqopuc7079482019-02-20 05:34:37 +000065 afterReceiveInterest(const FaceEndpoint& ingress, const Interest& interest,
Teng Liang7003e0b2018-03-03 16:03:30 -070066 const shared_ptr<pit::Entry>& pitEntry) override
67 {
ashiqopuc7079482019-02-20 05:34:37 +000068 DummyStrategy::afterReceiveInterest(ingress, interest, pitEntry);
Teng Liang7003e0b2018-03-03 16:03:30 -070069
70 if (afterReceiveInterest_count <= 1) {
71 setExpiryTimer(pitEntry, 190_ms);
72 }
73 }
74
75 void
76 beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +000077 const FaceEndpoint& ingress, const Data& data) override
Teng Liang7003e0b2018-03-03 16:03:30 -070078 {
ashiqopuc7079482019-02-20 05:34:37 +000079 DummyStrategy::beforeSatisfyInterest(pitEntry, ingress, data);
Teng Liang7003e0b2018-03-03 16:03:30 -070080
Teng Liang43bb2312018-03-26 04:16:42 -070081 if (beforeSatisfyInterest_count <= 2) {
Teng Liang7003e0b2018-03-03 16:03:30 -070082 setExpiryTimer(pitEntry, 190_ms);
83 }
84 }
85
86 void
Teng Liang85a36632018-03-21 05:59:34 -070087 afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +000088 const FaceEndpoint& ingress, const Data& data) override
Teng Liang85a36632018-03-21 05:59:34 -070089 {
90 if (afterContentStoreHit_count == 0) {
91 setExpiryTimer(pitEntry, 190_ms);
92 }
93
ashiqopuc7079482019-02-20 05:34:37 +000094 DummyStrategy::afterContentStoreHit(pitEntry, ingress, data);
Teng Liang85a36632018-03-21 05:59:34 -070095 }
96
97 void
Teng Liang43bb2312018-03-26 04:16:42 -070098 afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +000099 const FaceEndpoint& ingress, const Data& data) override
Teng Liang43bb2312018-03-26 04:16:42 -0700100 {
101 ++afterReceiveData_count;
102
103 if (afterReceiveData_count <= 2) {
104 setExpiryTimer(pitEntry, 290_ms);
105 }
106
ashiqopuc7079482019-02-20 05:34:37 +0000107 this->sendDataToAll(pitEntry, ingress, data);
Teng Liang43bb2312018-03-26 04:16:42 -0700108 }
109
110 void
ashiqopuc7079482019-02-20 05:34:37 +0000111 afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack& nack,
Teng Liang7003e0b2018-03-03 16:03:30 -0700112 const shared_ptr<pit::Entry>& pitEntry) override
113 {
ashiqopuc7079482019-02-20 05:34:37 +0000114 DummyStrategy::afterReceiveNack(ingress, nack, pitEntry);
Teng Liang7003e0b2018-03-03 16:03:30 -0700115
116 if (afterReceiveNack_count <= 1) {
117 setExpiryTimer(pitEntry, 50_ms);
118 }
119 }
120};
121
122BOOST_AUTO_TEST_CASE(UnsatisfiedInterest)
123{
124 Forwarder forwarder;
125
126 auto face1 = make_shared<DummyFace>();
127 auto face2 = make_shared<DummyFace>();
128 forwarder.addFace(face1);
129 forwarder.addFace(face2);
130
131 Pit& pit = forwarder.getPit();
132
133 shared_ptr<Interest> interest1 = makeInterest("/A/0");
134 shared_ptr<Interest> interest2 = makeInterest("/A/1");
135 interest1->setInterestLifetime(90_ms);
136 interest2->setInterestLifetime(90_ms);
137
138 face1->receiveInterest(*interest1);
139 face2->receiveInterest(*interest2);
140 BOOST_CHECK_EQUAL(pit.size(), 2);
141
142 this->advanceClocks(100_ms);
143 BOOST_CHECK_EQUAL(pit.size(), 0);
144}
145
146BOOST_AUTO_TEST_CASE(SatisfiedInterest)
147{
148 Forwarder forwarder;
149
150 auto face1 = make_shared<DummyFace>();
151 auto face2 = make_shared<DummyFace>();
152 forwarder.addFace(face1);
153 forwarder.addFace(face2);
154
155 Pit& pit = forwarder.getPit();
156
157 shared_ptr<Interest> interest = makeInterest("/A/0");
158 interest->setInterestLifetime(90_ms);
159 shared_ptr<Data> data = makeData("/A/0");
160
161 face1->receiveInterest(*interest);
162
163 this->advanceClocks(30_ms);
164 face2->receiveData(*data);
165
166 this->advanceClocks(1_ms);
167 BOOST_CHECK_EQUAL(pit.size(), 0);
168}
169
Teng Liang85a36632018-03-21 05:59:34 -0700170BOOST_AUTO_TEST_CASE(CsHit)
171{
172 Forwarder forwarder;
173
174 auto face1 = make_shared<DummyFace>();
175 auto face2 = make_shared<DummyFace>();
176 forwarder.addFace(face1);
177 forwarder.addFace(face2);
178
179 Name strategyA("/strategyA/%FD%01");
180 PitExpiryTestStrategy::registerAs(strategyA);
181 choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
182
183 shared_ptr<Interest> interest = makeInterest("/A/0");
184 interest->setInterestLifetime(90_ms);
185
186 shared_ptr<Data> data = makeData("/A/0");
187 data->setTag(make_shared<lp::IncomingFaceIdTag>(face2->getId()));
188
189 Pit& pit = forwarder.getPit();
190 BOOST_CHECK_EQUAL(pit.size(), 0);
191
192 Cs& cs = forwarder.getCs();
193 cs.insert(*data);
194
195 face1->receiveInterest(*interest);
196 this->advanceClocks(1_ms);
197 BOOST_CHECK_EQUAL(pit.size(), 1);
198
199 this->advanceClocks(190_ms);
200 BOOST_CHECK_EQUAL(pit.size(), 0);
201
202 face1->receiveInterest(*interest);
203 this->advanceClocks(1_ms);
204 BOOST_CHECK_EQUAL(pit.size(), 0);
205}
206
Teng Liang7003e0b2018-03-03 16:03:30 -0700207BOOST_AUTO_TEST_CASE(ReceiveNack)
208{
209 Forwarder forwarder;
210
211 auto face1 = make_shared<DummyFace>();
212 auto face2 = make_shared<DummyFace>();
213 auto face3 = make_shared<DummyFace>();
214 forwarder.addFace(face1);
215 forwarder.addFace(face2);
216 forwarder.addFace(face3);
217
218 Name strategyA("/strategyA/%FD%01");
219 PitExpiryTestStrategy::registerAs(strategyA);
220 choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
221
222 Pit& pit = forwarder.getPit();
223
224 shared_ptr<Interest> interest = makeInterest("/A/0", 562);
225 interest->setInterestLifetime(90_ms);
226 lp::Nack nack = makeNack("/A/0", 562, lp::NackReason::CONGESTION);
227
228 face1->receiveInterest(*interest);
229 auto entry = pit.find(*interest);
ashiqopud3ae85d2019-02-17 02:29:55 +0000230 entry->insertOrUpdateOutRecord(*face2, 0, *interest);
231 entry->insertOrUpdateOutRecord(*face3, 0, *interest);
Teng Liang7003e0b2018-03-03 16:03:30 -0700232
233 this->advanceClocks(10_ms);
234 face2->receiveNack(nack);
235
236 this->advanceClocks(1_ms);
237 BOOST_CHECK_EQUAL(pit.size(), 1);
238
239 this->advanceClocks(50_ms);
240 BOOST_CHECK_EQUAL(pit.size(), 0);
241}
242
243BOOST_AUTO_TEST_CASE(ResetTimerAfterReceiveInterest)
244{
245 Forwarder forwarder;
246
247 auto face = make_shared<DummyFace>();
248 forwarder.addFace(face);
249
250 Name strategyA("/strategyA/%FD%01");
251 PitExpiryTestStrategy::registerAs(strategyA);
252 choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
253
254 Pit& pit = forwarder.getPit();
255
256 shared_ptr<Interest> interest = makeInterest("/A/0");
257 interest->setInterestLifetime(90_ms);
258
259 face->receiveInterest(*interest);
260 BOOST_CHECK_EQUAL(pit.size(), 1);
261
262 this->advanceClocks(100_ms);
263 BOOST_CHECK_EQUAL(pit.size(), 1);
264
265 this->advanceClocks(100_ms);
266 BOOST_CHECK_EQUAL(pit.size(), 0);
267}
268
269BOOST_AUTO_TEST_CASE(ResetTimerBeforeSatisfyInterest)
270{
271 Forwarder forwarder;
272
273 auto face1 = make_shared<DummyFace>();
274 auto face2 = make_shared<DummyFace>();
Teng Liang43bb2312018-03-26 04:16:42 -0700275 auto face3 = make_shared<DummyFace>();
276 forwarder.addFace(face1);
277 forwarder.addFace(face2);
278 forwarder.addFace(face3);
279
280 Name strategyA("/strategyA/%FD%01");
281 Name strategyB("/strategyB/%FD%01");
282 PitExpiryTestStrategy::registerAs(strategyA);
283 PitExpiryTestStrategy::registerAs(strategyB);
284 auto& sA = choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
285 auto& sB = choose<PitExpiryTestStrategy>(forwarder, "/A/0", strategyB);
286 Pit& pit = forwarder.getPit();
287
288 shared_ptr<Interest> interest1 = makeInterest("/A");
289 shared_ptr<Interest> interest2 = makeInterest("/A/0");
290 interest1->setInterestLifetime(90_ms);
291 interest2->setInterestLifetime(90_ms);
292 shared_ptr<Data> data = makeData("/A/0");
293
294 face1->receiveInterest(*interest1);
295 face2->receiveInterest(*interest2);
296 BOOST_CHECK_EQUAL(pit.size(), 2);
297
298 // beforeSatisfyInterest: the first Data prolongs PIT expiry timer by 190 ms
299 this->advanceClocks(30_ms);
300 face3->receiveData(*data);
301 this->advanceClocks(189_ms);
302 BOOST_CHECK_EQUAL(pit.size(), 2);
303 this->advanceClocks(2_ms);
304 BOOST_CHECK_EQUAL(pit.size(), 0);
305
306 face1->receiveInterest(*interest1);
307 face2->receiveInterest(*interest2);
308
309 // beforeSatisfyInterest: the second Data prolongs PIT expiry timer
310 // and the third one sets the timer to now
311 this->advanceClocks(30_ms);
312 face3->receiveData(*data);
313 this->advanceClocks(1_ms);
314 BOOST_CHECK_EQUAL(pit.size(), 2);
315
316 this->advanceClocks(30_ms);
317 face3->receiveData(*data);
318 this->advanceClocks(1_ms);
319 BOOST_CHECK_EQUAL(pit.size(), 0);
320
321 BOOST_CHECK_EQUAL(sA.beforeSatisfyInterest_count, 3);
322 BOOST_CHECK_EQUAL(sB.beforeSatisfyInterest_count, 3);
323 BOOST_CHECK_EQUAL(sA.afterReceiveData_count, 0);
324 BOOST_CHECK_EQUAL(sB.afterReceiveData_count, 0);
325}
326
327BOOST_AUTO_TEST_CASE(ResetTimerAfterReceiveData)
328{
329 Forwarder forwarder;
330
331 auto face1 = make_shared<DummyFace>();
332 auto face2 = make_shared<DummyFace>();
Teng Liang7003e0b2018-03-03 16:03:30 -0700333 forwarder.addFace(face1);
334 forwarder.addFace(face2);
335
336 Name strategyA("/strategyA/%FD%01");
337 PitExpiryTestStrategy::registerAs(strategyA);
Teng Liang43bb2312018-03-26 04:16:42 -0700338 auto& sA = choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
Teng Liang7003e0b2018-03-03 16:03:30 -0700339
340 Pit& pit = forwarder.getPit();
341
342 shared_ptr<Interest> interest = makeInterest("/A/0");
343 interest->setInterestLifetime(90_ms);
344 shared_ptr<Data> data = makeData("/A/0");
345
346 face1->receiveInterest(*interest);
347
Teng Liang43bb2312018-03-26 04:16:42 -0700348 // afterReceiveData: the first Data prolongs PIT expiry timer by 290 ms
Teng Liang7003e0b2018-03-03 16:03:30 -0700349 this->advanceClocks(30_ms);
350 face2->receiveData(*data);
Teng Liang43bb2312018-03-26 04:16:42 -0700351 this->advanceClocks(289_ms);
352 BOOST_CHECK_EQUAL(pit.size(), 1);
353 this->advanceClocks(2_ms);
354 BOOST_CHECK_EQUAL(pit.size(), 0);
Teng Liang7003e0b2018-03-03 16:03:30 -0700355
Teng Liang43bb2312018-03-26 04:16:42 -0700356 face1->receiveInterest(*interest);
357
358 // afterReceiveData: the second Data prolongs PIT expiry timer
359 // and the third one sets the timer to now
360 this->advanceClocks(30_ms);
361 face2->receiveData(*data);
Teng Liang7003e0b2018-03-03 16:03:30 -0700362 this->advanceClocks(1_ms);
363 BOOST_CHECK_EQUAL(pit.size(), 1);
364
365 this->advanceClocks(30_ms);
366 face2->receiveData(*data);
Teng Liang7003e0b2018-03-03 16:03:30 -0700367 this->advanceClocks(1_ms);
368 BOOST_CHECK_EQUAL(pit.size(), 0);
Teng Liang43bb2312018-03-26 04:16:42 -0700369
370 BOOST_CHECK_EQUAL(sA.beforeSatisfyInterest_count, 0);
371 BOOST_CHECK_EQUAL(sA.afterReceiveData_count, 3);
Teng Liang7003e0b2018-03-03 16:03:30 -0700372}
373
374BOOST_AUTO_TEST_CASE(ReceiveNackAfterResetTimer)
375{
376 Forwarder forwarder;
377
378 auto face1 = make_shared<DummyFace>();
379 auto face2 = make_shared<DummyFace>();
380 auto face3 = make_shared<DummyFace>();
381 forwarder.addFace(face1);
382 forwarder.addFace(face2);
383 forwarder.addFace(face3);
384
385 Name strategyA("/strategyA/%FD%01");
386 PitExpiryTestStrategy::registerAs(strategyA);
387 choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
388
389 Pit& pit = forwarder.getPit();
390
391 shared_ptr<Interest> interest = makeInterest("/A/0", 562);
392 interest->setInterestLifetime(90_ms);
393 lp::Nack nack = makeNack("/A/0", 562, lp::NackReason::CONGESTION);
394
395 face1->receiveInterest(*interest);
396 auto entry = pit.find(*interest);
ashiqopud3ae85d2019-02-17 02:29:55 +0000397 entry->insertOrUpdateOutRecord(*face2, 0, *interest);
398 entry->insertOrUpdateOutRecord(*face3, 0, *interest);
Teng Liang7003e0b2018-03-03 16:03:30 -0700399
400 //pitEntry is not erased after receiving the first Nack
401 this->advanceClocks(10_ms);
402 face2->receiveNack(nack);
403 this->advanceClocks(1_ms);
404 BOOST_CHECK_EQUAL(pit.size(), 1);
405
406 //pitEntry is erased after receiving the second Nack
407 this->advanceClocks(10_ms);
408 face3->receiveNack(nack);
409 this->advanceClocks(1_ms);
410 BOOST_CHECK_EQUAL(pit.size(), 0);
411}
412
413BOOST_AUTO_TEST_SUITE_END() // TestPitExpiry
414BOOST_AUTO_TEST_SUITE_END() // Fw
415
416} // namespace tests
417} // namespace fw
418} // namespace nfd