blob: 9fec06b237343e7e70059a3d82bdf4b23e675c6f [file] [log] [blame]
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Hila Ben Abraham39a79be2016-03-30 22:00:55 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Junxiao Shi63162202015-01-14 22:27:33 -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.
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"
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070028#include "topology-tester.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070029#include "tests/daemon/face/dummy-face.hpp"
30#include "tests/limited-io.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070031
Junxiao Shid9ee45c2014-02-27 15:38:11 -070032#include "tests/test-common.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070033
34namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080035namespace fw {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070036namespace tests {
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070037
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080038using namespace nfd::tests;
39
Junxiao Shi5e5e4452015-09-24 16:56:52 -070040BOOST_AUTO_TEST_SUITE(Fw)
41BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, UnitTestTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070042
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070043using fw::NccStrategy;
44
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070045// NccStrategy is fairly complex.
46// The most important property is:
47// it remembers which upstream is the fastest to return Data,
48// and favors this upstream in subsequent Interests.
49BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
50{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070051 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070052 Forwarder forwarder;
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070053 typedef StrategyTester<NccStrategy> NccStrategyTester;
Alexander Afanasyevf6980282014-05-13 18:28:40 -070054 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -070055 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070056
57 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
58 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
59 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
60 forwarder.addFace(face1);
61 forwarder.addFace(face2);
62 forwarder.addFace(face3);
63
64 Fib& fib = forwarder.getFib();
65 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070066 fibEntry->addNextHop(face1, 10);
67 fibEntry->addNextHop(face2, 20);
68
Junxiao Shi7bb01512014-03-05 21:34:09 -070069 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
70 strategyChoice.install(strategy);
71 strategyChoice.insert(Name(), strategy->getName());
72
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073 Pit& pit = forwarder.getPit();
74
75 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070076 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070077 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070078 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070079 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
80
81 pitEntry1->insertOrUpdateInRecord(face3, interest1);
Junxiao Shi8d843142016-07-11 22:42:42 +000082 strategy->afterReceiveInterest(*face3, interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070083
84 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070085 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shi5e5e4452015-09-24 16:56:52 -070086 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
87 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070088
89 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070090 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -070091 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
92 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070093
94 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070095 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070096 Data& data1 = *data1p;
Junxiao Shi82e7f582014-09-07 15:15:40 -070097 strategy->beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070098 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070099
100 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -0700101 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700102 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700103 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700104 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
105
106 pitEntry2->insertOrUpdateInRecord(face3, interest2);
Junxiao Shi8d843142016-07-11 22:42:42 +0000107 strategy->afterReceiveInterest(*face3, interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700108
109 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700110 this->advanceClocks(time::milliseconds(1));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700111 BOOST_REQUIRE_GE(strategy->sendInterestHistory.size(), 3);
112 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700113}
114
Junxiao Shicbb490a2014-08-13 12:24:24 -0700115BOOST_AUTO_TEST_CASE(Bug1853)
116{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700117 Forwarder forwarder;
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700118 typedef StrategyTester<NccStrategy> NccStrategyTester;
Junxiao Shicbb490a2014-08-13 12:24:24 -0700119 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700120
121 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
122 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
123 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
124 forwarder.addFace(face1);
125 forwarder.addFace(face2);
126 forwarder.addFace(face3);
127
128 Fib& fib = forwarder.getFib();
129 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
130 fibEntry->addNextHop(face1, 10);
131
132 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
133 strategyChoice.install(strategy);
134 strategyChoice.insert(Name(), strategy->getName());
135
136 Pit& pit = forwarder.getPit();
137
138 // first Interest: strategy follows routing and forwards to face1
139 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
140 interest1->setInterestLifetime(time::milliseconds(8000));
141 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
142
143 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
Junxiao Shi8d843142016-07-11 22:42:42 +0000144 strategy->afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700145
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700146 this->advanceClocks(time::milliseconds(1));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700147 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
148 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700149
150 // face1 responds
151 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shi82e7f582014-09-07 15:15:40 -0700152 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700153 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700154
155 // second Interest: bestFace is face1, nUpstreams becomes 0,
156 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
157 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
158 interest2->setInterestLifetime(time::milliseconds(8000));
159 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
160
161 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
Junxiao Shi8d843142016-07-11 22:42:42 +0000162 strategy->afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700163
164 // FIB entry is changed before doPropagate executes
165 fibEntry->addNextHop(face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700166 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700167}
168
Junxiao Shi82e7f582014-09-07 15:15:40 -0700169BOOST_AUTO_TEST_CASE(Bug1961)
170{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700171 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700172 Forwarder forwarder;
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700173 typedef StrategyTester<NccStrategy> NccStrategyTester;
Junxiao Shi82e7f582014-09-07 15:15:40 -0700174 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700175 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700176
177 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
178 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
179 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
180 forwarder.addFace(face1);
181 forwarder.addFace(face2);
182 forwarder.addFace(face3);
183
184 Fib& fib = forwarder.getFib();
185 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
186 fibEntry->addNextHop(face1, 10);
187 fibEntry->addNextHop(face2, 20);
188
189 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
190 strategyChoice.install(strategy);
191 strategyChoice.insert(Name(), strategy->getName());
192
193 Pit& pit = forwarder.getPit();
194
195 // first Interest: strategy forwards to face1 and face2
196 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
197 interest1->setInterestLifetime(time::milliseconds(2000));
198 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
199
200 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
Junxiao Shi8d843142016-07-11 22:42:42 +0000201 strategy->afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700202 limitedIo.run(2 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700203 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700204 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
205 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face1->getId());
206 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700207
208 // face1 responds
209 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
210 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700211 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700212 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700213 // face2 also responds
214 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700215 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700216
217 // second Interest: bestFace should be face 1
218 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
219 interest2->setInterestLifetime(time::milliseconds(2000));
220 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
221
222 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
Junxiao Shi8d843142016-07-11 22:42:42 +0000223 strategy->afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700224 limitedIo.run(3 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700225 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700226
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700227 BOOST_REQUIRE_GE(strategy->sendInterestHistory.size(), 3);
228 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700229}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700230
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700231BOOST_AUTO_TEST_CASE(Bug1971)
232{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700233 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700234 Forwarder forwarder;
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700235 typedef StrategyTester<NccStrategy> NccStrategyTester;
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700236 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700237 strategy->afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700238
239 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
240 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
241 forwarder.addFace(face1);
242 forwarder.addFace(face2);
243
244 Fib& fib = forwarder.getFib();
245 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
246 fibEntry->addNextHop(face2, 10);
247
248 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
249 strategyChoice.install(strategy);
250 strategyChoice.insert(Name(), strategy->getName());
251
252 Pit& pit = forwarder.getPit();
253
254 // first Interest: strategy forwards to face2
255 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
256 interest1->setInterestLifetime(time::milliseconds(2000));
257 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
258
259 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi8d843142016-07-11 22:42:42 +0000260 strategy->afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700261 limitedIo.run(1 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700262 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700263 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
264 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700265
266 // face2 responds
267 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
268 data1->setFreshnessPeriod(time::milliseconds(5));
269 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700270 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700271 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700272 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700273
274 // similar Interest: strategy should still forward it
275 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi8d843142016-07-11 22:42:42 +0000276 strategy->afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700277 limitedIo.run(2 - strategy->sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700278 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700279 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 2);
280 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700281}
282
Junxiao Shi63162202015-01-14 22:27:33 -0700283BOOST_AUTO_TEST_CASE(Bug1998)
284{
285 Forwarder forwarder;
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700286 typedef StrategyTester<NccStrategy> NccStrategyTester;
Junxiao Shi63162202015-01-14 22:27:33 -0700287 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
288
289 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
290 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
291 forwarder.addFace(face1);
292 forwarder.addFace(face2);
293
294 Fib& fib = forwarder.getFib();
295 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
296 fibEntry->addNextHop(face1, 10); // face1 is top-ranked nexthop
297 fibEntry->addNextHop(face2, 20);
298
299 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
300 strategyChoice.install(strategy);
301 strategyChoice.insert(Name(), strategy->getName());
302
303 Pit& pit = forwarder.getPit();
304
305 // Interest comes from face1, which is sole downstream
306 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
307 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
308 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
309
Junxiao Shi8d843142016-07-11 22:42:42 +0000310 strategy->afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700311
312 // Interest shall go to face2, not loop back to face1
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700313 BOOST_REQUIRE_EQUAL(strategy->sendInterestHistory.size(), 1);
314 BOOST_CHECK_EQUAL(strategy->sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700315}
316
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700317BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
318BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
319{
320 /*
321 * /----------\
322 * | consumer |
323 * \----------/
324 * |
325 * |
326 * +---+ 5ms +---+
327 * | A |-------| B |
328 * +---+ +---+
329 * | |
330 * | 5ms | 15ms/5ms
331 * | |
332 * +---+ +---+
333 * | C |-------| D |
334 * +---+ 15ms +---+
335 * /5ms |
336 * |
337 * /----------\
338 * | producer |
339 * \----------/
340 */
341
342 TopologyTester topo;
343 TopologyNode nodeA = topo.addForwarder("A"),
344 nodeB = topo.addForwarder("B"),
345 nodeC = topo.addForwarder("C"),
346 nodeD = topo.addForwarder("D");
347
348 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
349 topo.setStrategy<NccStrategy>(node);
350 }
351
352 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
353 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
354 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
355 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
356
357 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
358 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
359 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
360 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
361
362 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
363 topo.addEchoProducer(producer->getClientFace());
364
365 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
366 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
367 time::milliseconds(100), 300);
368
369 auto getMeInfo = [&] () -> shared_ptr<NccStrategy::MeasurementsEntryInfo> {
370 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
371 shared_ptr<measurements::Entry> me = measurements.findExactMatch("ndn:/P");
372 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
373 };
374
375 // NccStrategy starts with an exploration period when the algorithm adjusts
376 // its prediction to converge near the path RTT.
377 bool isExplorationFinished = false;
378 const time::milliseconds TRUE_RTT1(40);
379 bool isLastPredictionUnder = true;
380 int nPredictionCrossings = 0;
381 for (int i = 0; i < 10000; ++i) {
382 this->advanceClocks(time::milliseconds(5));
383 auto meInfo = getMeInfo();
384 if (meInfo == nullptr) {
385 continue;
386 }
387
388 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
389 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
390 isLastPredictionUnder = !isLastPredictionUnder;
391 if (++nPredictionCrossings > 6) {
392 isExplorationFinished = true;
393 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
394 break;
395 }
396 }
397 }
398 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
399
400 // NccStrategy has selected one path as the best.
401 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
402 // However, this won't happen due to a weakness in NccStrategy.
403 // See http://redmine.named-data.net/issues/3411#note-4
404 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
405 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
406 linkCD->setDelay(time::milliseconds(5));
407 }
408 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
409 linkBD->setDelay(time::milliseconds(5));
410 }
411 else {
412 BOOST_FAIL("unexpected best face");
413 }
414
415 bool isNewBestChosen = false;
416 for (int i = 0; i < 10000; ++i) {
417 this->advanceClocks(time::milliseconds(5));
418 auto meInfo = getMeInfo();
419 if (meInfo == nullptr) {
420 continue;
421 }
422
423 if (meInfo->bestFace.lock() != bestFace1) {
424 isNewBestChosen = true;
425 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
426 break;
427 }
428 }
429 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
430}
431
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700432BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
433BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700434
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700435} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800436} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700437} // namespace nfd