blob: a7924045e0d8ff94aa6eb0bff20062cfe8636835 [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
Junxiao Shic34d1672016-12-09 15:57:59 +000043BOOST_AUTO_TEST_CASE(Registration)
44{
45 BOOST_CHECK_EQUAL(Strategy::listRegistered().count(NccStrategy::STRATEGY_NAME), 1);
46}
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070047
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070048// NccStrategy is fairly complex.
49// The most important property is:
50// it remembers which upstream is the fastest to return Data,
51// and favors this upstream in subsequent Interests.
52BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
53{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070054 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070055 Forwarder forwarder;
Junxiao Shia49a1ab2016-07-15 18:24:36 +000056 StrategyTester<NccStrategy>& strategy = choose<StrategyTester<NccStrategy>>(forwarder);
57 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070058
59 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
60 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
61 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
62 forwarder.addFace(face1);
63 forwarder.addFace(face2);
64 forwarder.addFace(face3);
65
66 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000067 fib::Entry& fibEntry = *fib.insert(Name()).first;
68 fibEntry.addNextHop(*face1, 10);
69 fibEntry.addNextHop(*face2, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070070
71 Pit& pit = forwarder.getPit();
72
73 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070074 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070075 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070076 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070077 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
78
Junxiao Shi9cff7792016-08-01 21:45:11 +000079 pitEntry1->insertOrUpdateInRecord(*face3, interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000080 strategy.afterReceiveInterest(*face3, interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070081
82 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070083 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000084 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
85 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070086
87 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070088 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +000089 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
90 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070091
92 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070093 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070094 Data& data1 = *data1p;
Junxiao Shia49a1ab2016-07-15 18:24:36 +000095 strategy.beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070096 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070097
98 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070099 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700100 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700101 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700102 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
103
Junxiao Shi9cff7792016-08-01 21:45:11 +0000104 pitEntry2->insertOrUpdateInRecord(*face3, interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000105 strategy.afterReceiveInterest(*face3, interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700106
107 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700108 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000109 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
110 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700111}
112
Junxiao Shicbb490a2014-08-13 12:24:24 -0700113BOOST_AUTO_TEST_CASE(Bug1853)
114{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700115 Forwarder forwarder;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000116 StrategyTester<NccStrategy>& strategy = choose<StrategyTester<NccStrategy>>(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();
Junxiao Shia6de4292016-07-12 02:08:10 +0000126 fib::Entry& fibEntry = *fib.insert(Name()).first;
127 fibEntry.addNextHop(*face1, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700128
Junxiao Shicbb490a2014-08-13 12:24:24 -0700129 Pit& pit = forwarder.getPit();
130
131 // first Interest: strategy follows routing and forwards to face1
132 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
133 interest1->setInterestLifetime(time::milliseconds(8000));
134 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
135
Junxiao Shi9cff7792016-08-01 21:45:11 +0000136 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000137 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700138
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700139 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000140 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
141 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700142
143 // face1 responds
144 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000145 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700146 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700147
148 // second Interest: bestFace is face1, nUpstreams becomes 0,
149 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
150 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
151 interest2->setInterestLifetime(time::milliseconds(8000));
152 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
153
Junxiao Shi9cff7792016-08-01 21:45:11 +0000154 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000155 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700156
157 // FIB entry is changed before doPropagate executes
Junxiao Shia6de4292016-07-12 02:08:10 +0000158 fibEntry.addNextHop(*face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700159 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700160}
161
Junxiao Shi82e7f582014-09-07 15:15:40 -0700162BOOST_AUTO_TEST_CASE(Bug1961)
163{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700164 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700165 Forwarder forwarder;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000166 StrategyTester<NccStrategy>& strategy = choose<StrategyTester<NccStrategy>>(forwarder);
167 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700168
169 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
170 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
171 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
172 forwarder.addFace(face1);
173 forwarder.addFace(face2);
174 forwarder.addFace(face3);
175
176 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000177 fib::Entry& fibEntry = *fib.insert(Name()).first;
178 fibEntry.addNextHop(*face1, 10);
179 fibEntry.addNextHop(*face2, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700180
Junxiao Shi82e7f582014-09-07 15:15:40 -0700181 Pit& pit = forwarder.getPit();
182
183 // first Interest: strategy forwards to face1 and face2
184 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
185 interest1->setInterestLifetime(time::milliseconds(2000));
186 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
187
Junxiao Shi9cff7792016-08-01 21:45:11 +0000188 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000189 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
190 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700191 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000192 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
193 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
194 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700195
196 // face1 responds
197 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000198 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700199 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700200 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700201 // face2 also responds
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000202 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700203 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700204
205 // second Interest: bestFace should be face 1
206 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
207 interest2->setInterestLifetime(time::milliseconds(2000));
208 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
209
Junxiao Shi9cff7792016-08-01 21:45:11 +0000210 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000211 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
212 limitedIo.run(3 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700213 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700214
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000215 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
216 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700217}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700218
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700219BOOST_AUTO_TEST_CASE(Bug1971)
220{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700221 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700222 Forwarder forwarder;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000223 StrategyTester<NccStrategy>& strategy = choose<StrategyTester<NccStrategy>>(forwarder);
224 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700225
226 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
227 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
228 forwarder.addFace(face1);
229 forwarder.addFace(face2);
230
231 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000232 fib::Entry& fibEntry = *fib.insert(Name()).first;
233 fibEntry.addNextHop(*face2, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700234
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700235 Pit& pit = forwarder.getPit();
236
237 // first Interest: strategy forwards to face2
238 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
239 interest1->setInterestLifetime(time::milliseconds(2000));
240 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
241
Junxiao Shi9cff7792016-08-01 21:45:11 +0000242 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000243 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
244 limitedIo.run(1 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700245 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000246 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
247 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700248
249 // face2 responds
250 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
251 data1->setFreshnessPeriod(time::milliseconds(5));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000252 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700253 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700254 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700255 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700256
257 // similar Interest: strategy should still forward it
Junxiao Shi9cff7792016-08-01 21:45:11 +0000258 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000259 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
260 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700261 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000262 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
263 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700264}
265
Junxiao Shi63162202015-01-14 22:27:33 -0700266BOOST_AUTO_TEST_CASE(Bug1998)
267{
268 Forwarder forwarder;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000269 StrategyTester<NccStrategy>& strategy = choose<StrategyTester<NccStrategy>>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700270
271 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
272 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
273 forwarder.addFace(face1);
274 forwarder.addFace(face2);
275
276 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000277 fib::Entry& fibEntry = *fib.insert(Name()).first;
278 fibEntry.addNextHop(*face1, 10); // face1 is top-ranked nexthop
279 fibEntry.addNextHop(*face2, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700280
Junxiao Shi63162202015-01-14 22:27:33 -0700281 Pit& pit = forwarder.getPit();
282
283 // Interest comes from face1, which is sole downstream
284 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
285 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000286 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700287
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000288 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700289
290 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000291 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
292 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700293}
294
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700295BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
296BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
297{
298 /*
299 * /----------\
300 * | consumer |
301 * \----------/
302 * |
303 * |
304 * +---+ 5ms +---+
305 * | A |-------| B |
306 * +---+ +---+
307 * | |
308 * | 5ms | 15ms/5ms
309 * | |
310 * +---+ +---+
311 * | C |-------| D |
312 * +---+ 15ms +---+
313 * /5ms |
314 * |
315 * /----------\
316 * | producer |
317 * \----------/
318 */
319
320 TopologyTester topo;
321 TopologyNode nodeA = topo.addForwarder("A"),
322 nodeB = topo.addForwarder("B"),
323 nodeC = topo.addForwarder("C"),
324 nodeD = topo.addForwarder("D");
325
326 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
327 topo.setStrategy<NccStrategy>(node);
328 }
329
330 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
331 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
332 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
333 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
334
335 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
336 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
337 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
338 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
339
340 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
341 topo.addEchoProducer(producer->getClientFace());
342
343 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
344 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
345 time::milliseconds(100), 300);
346
Junxiao Shifc021862016-08-25 21:51:18 +0000347 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700348 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000349 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700350 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
351 };
352
353 // NccStrategy starts with an exploration period when the algorithm adjusts
354 // its prediction to converge near the path RTT.
355 bool isExplorationFinished = false;
356 const time::milliseconds TRUE_RTT1(40);
357 bool isLastPredictionUnder = true;
358 int nPredictionCrossings = 0;
359 for (int i = 0; i < 10000; ++i) {
360 this->advanceClocks(time::milliseconds(5));
361 auto meInfo = getMeInfo();
362 if (meInfo == nullptr) {
363 continue;
364 }
365
366 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
367 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
368 isLastPredictionUnder = !isLastPredictionUnder;
369 if (++nPredictionCrossings > 6) {
370 isExplorationFinished = true;
371 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
372 break;
373 }
374 }
375 }
376 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
377
378 // NccStrategy has selected one path as the best.
379 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
380 // However, this won't happen due to a weakness in NccStrategy.
381 // See http://redmine.named-data.net/issues/3411#note-4
382 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
383 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
384 linkCD->setDelay(time::milliseconds(5));
385 }
386 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
387 linkBD->setDelay(time::milliseconds(5));
388 }
389 else {
390 BOOST_FAIL("unexpected best face");
391 }
392
393 bool isNewBestChosen = false;
394 for (int i = 0; i < 10000; ++i) {
395 this->advanceClocks(time::milliseconds(5));
396 auto meInfo = getMeInfo();
397 if (meInfo == nullptr) {
398 continue;
399 }
400
401 if (meInfo->bestFace.lock() != bestFace1) {
402 isNewBestChosen = true;
403 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
404 break;
405 }
406 }
407 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
408}
409
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700410BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
411BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700412
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700413} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800414} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700415} // namespace nfd