blob: 889b2e2cffd897be8bd546a232966d7d2ff82928 [file] [log] [blame]
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi63162202015-01-14 22:27:33 -07003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Junxiao Shi82e7f582014-09-07 15:15:40 -070024 */
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070025
26#include "fw/ncc-strategy.hpp"
27#include "strategy-tester.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070028#include "tests/daemon/face/dummy-face.hpp"
29#include "tests/limited-io.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070030
Junxiao Shid9ee45c2014-02-27 15:38:11 -070031#include "tests/test-common.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070032
33namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080034namespace fw {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070036
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080037using namespace nfd::tests;
38
Junxiao Shi5e5e4452015-09-24 16:56:52 -070039BOOST_AUTO_TEST_SUITE(Fw)
40BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, UnitTestTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070041
42// NccStrategy is fairly complex.
43// The most important property is:
44// it remembers which upstream is the fastest to return Data,
45// and favors this upstream in subsequent Interests.
46BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
47{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070048 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070049 Forwarder forwarder;
50 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
Alexander Afanasyevf6980282014-05-13 18:28:40 -070051 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -070052 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070053
54 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
55 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
56 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
57 forwarder.addFace(face1);
58 forwarder.addFace(face2);
59 forwarder.addFace(face3);
60
61 Fib& fib = forwarder.getFib();
62 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070063 fibEntry->addNextHop(face1, 10);
64 fibEntry->addNextHop(face2, 20);
65
Junxiao Shi7bb01512014-03-05 21:34:09 -070066 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
67 strategyChoice.install(strategy);
68 strategyChoice.insert(Name(), strategy->getName());
69
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070070 Pit& pit = forwarder.getPit();
71
72 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070073 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070074 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070075 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070076 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
77
78 pitEntry1->insertOrUpdateInRecord(face3, interest1);
79 strategy->afterReceiveInterest(*face3, interest1, fibEntry, pitEntry1);
80
81 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070082 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070083 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
84 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070085
86 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070087 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -070088 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
89 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070090
91 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070092 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070093 Data& data1 = *data1p;
Junxiao Shi82e7f582014-09-07 15:15:40 -070094 strategy->beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070095 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070096
97 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070098 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070099 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700100 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700101 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
102
103 pitEntry2->insertOrUpdateInRecord(face3, interest2);
104 strategy->afterReceiveInterest(*face3, interest2, fibEntry, pitEntry2);
105
106 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700107 this->advanceClocks(time::milliseconds(1));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700108 BOOST_REQUIRE_GE(strategy->sendInterestHistory.size(), 3);
109 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700110}
111
Junxiao Shicbb490a2014-08-13 12:24:24 -0700112BOOST_AUTO_TEST_CASE(Bug1853)
113{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700114 Forwarder forwarder;
115 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
116 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700117
118 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
119 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
120 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
121 forwarder.addFace(face1);
122 forwarder.addFace(face2);
123 forwarder.addFace(face3);
124
125 Fib& fib = forwarder.getFib();
126 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
127 fibEntry->addNextHop(face1, 10);
128
129 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
130 strategyChoice.install(strategy);
131 strategyChoice.insert(Name(), strategy->getName());
132
133 Pit& pit = forwarder.getPit();
134
135 // first Interest: strategy follows routing and forwards to face1
136 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
137 interest1->setInterestLifetime(time::milliseconds(8000));
138 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
139
140 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
141 strategy->afterReceiveInterest(*face3, *interest1, fibEntry, pitEntry1);
142
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700143 this->advanceClocks(time::milliseconds(1));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700144 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
145 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700146
147 // face1 responds
148 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shi82e7f582014-09-07 15:15:40 -0700149 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700150 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700151
152 // second Interest: bestFace is face1, nUpstreams becomes 0,
153 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
154 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
155 interest2->setInterestLifetime(time::milliseconds(8000));
156 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
157
158 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
159 strategy->afterReceiveInterest(*face3, *interest2, fibEntry, pitEntry2);
160
161 // FIB entry is changed before doPropagate executes
162 fibEntry->addNextHop(face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700163 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700164}
165
Junxiao Shi82e7f582014-09-07 15:15:40 -0700166BOOST_AUTO_TEST_CASE(Bug1961)
167{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700168 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700169 Forwarder forwarder;
170 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
171 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700172 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700173
174 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
175 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
176 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
177 forwarder.addFace(face1);
178 forwarder.addFace(face2);
179 forwarder.addFace(face3);
180
181 Fib& fib = forwarder.getFib();
182 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
183 fibEntry->addNextHop(face1, 10);
184 fibEntry->addNextHop(face2, 20);
185
186 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
187 strategyChoice.install(strategy);
188 strategyChoice.insert(Name(), strategy->getName());
189
190 Pit& pit = forwarder.getPit();
191
192 // first Interest: strategy forwards to face1 and face2
193 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
194 interest1->setInterestLifetime(time::milliseconds(2000));
195 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
196
197 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
198 strategy->afterReceiveInterest(*face3, *interest1, fibEntry, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700199 limitedIo.run(2 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700200 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700201 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
202 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
203 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700204
205 // face1 responds
206 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
207 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
208 pitEntry1->deleteInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700209 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700210 // face2 also responds
211 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700212 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700213
214 // second Interest: bestFace should be face 1
215 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
216 interest2->setInterestLifetime(time::milliseconds(2000));
217 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
218
219 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
220 strategy->afterReceiveInterest(*face3, *interest2, fibEntry, pitEntry2);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700221 limitedIo.run(3 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700222 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700223
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700224 BOOST_REQUIRE_GE(strategy->sendInterestHistory.size(), 3);
225 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700226}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700227
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700228BOOST_AUTO_TEST_CASE(Bug1971)
229{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700230 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700231 Forwarder forwarder;
232 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
233 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700234 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700235
236 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
237 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
238 forwarder.addFace(face1);
239 forwarder.addFace(face2);
240
241 Fib& fib = forwarder.getFib();
242 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
243 fibEntry->addNextHop(face2, 10);
244
245 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
246 strategyChoice.install(strategy);
247 strategyChoice.insert(Name(), strategy->getName());
248
249 Pit& pit = forwarder.getPit();
250
251 // first Interest: strategy forwards to face2
252 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
253 interest1->setInterestLifetime(time::milliseconds(2000));
254 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
255
256 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
257 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700258 limitedIo.run(1 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700259 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700260 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
261 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700262
263 // face2 responds
264 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
265 data1->setFreshnessPeriod(time::milliseconds(5));
266 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700267 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700268 pitEntry1->deleteInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700269 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700270
271 // similar Interest: strategy should still forward it
272 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
273 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700274 limitedIo.run(2 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700275 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700276 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
277 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700278}
279
Junxiao Shi63162202015-01-14 22:27:33 -0700280BOOST_AUTO_TEST_CASE(Bug1998)
281{
282 Forwarder forwarder;
283 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
284 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
285
286 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
287 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
288 forwarder.addFace(face1);
289 forwarder.addFace(face2);
290
291 Fib& fib = forwarder.getFib();
292 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
293 fibEntry->addNextHop(face1, 10); // face1 is top-ranked nexthop
294 fibEntry->addNextHop(face2, 20);
295
296 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
297 strategyChoice.install(strategy);
298 strategyChoice.insert(Name(), strategy->getName());
299
300 Pit& pit = forwarder.getPit();
301
302 // Interest comes from face1, which is sole downstream
303 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
304 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
305 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
306
307 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
308
309 // Interest shall go to face2, not loop back to face1
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700310 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
311 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700312}
313
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700314BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
315BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700316
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700317} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800318} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700319} // namespace nfd