blob: bc482e52766d126cf0f1c6edebffae56885ff345 [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 Shi890afe92016-12-15 14:34:34 +000040typedef StrategyTester<NccStrategy> NccStrategyTester;
41NFD_REGISTER_STRATEGY(NccStrategyTester);
42
Junxiao Shi5e5e4452015-09-24 16:56:52 -070043BOOST_AUTO_TEST_SUITE(Fw)
44BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, UnitTestTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070045
Junxiao Shic34d1672016-12-09 15:57:59 +000046BOOST_AUTO_TEST_CASE(Registration)
47{
Junxiao Shi037f4ab2016-12-13 04:27:06 +000048 BOOST_CHECK_EQUAL(Strategy::listRegistered().count(NccStrategy::getStrategyName()), 1);
Junxiao Shic34d1672016-12-09 15:57:59 +000049}
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070050
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070051// NccStrategy is fairly complex.
52// The most important property is:
53// it remembers which upstream is the fastest to return Data,
54// and favors this upstream in subsequent Interests.
55BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
56{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070057 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070058 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +000059 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000060 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070061
62 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
63 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
64 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
65 forwarder.addFace(face1);
66 forwarder.addFace(face2);
67 forwarder.addFace(face3);
68
69 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000070 fib::Entry& fibEntry = *fib.insert(Name()).first;
71 fibEntry.addNextHop(*face1, 10);
72 fibEntry.addNextHop(*face2, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073
74 Pit& pit = forwarder.getPit();
75
76 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070077 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070078 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070079 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070080 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
81
Junxiao Shi9cff7792016-08-01 21:45:11 +000082 pitEntry1->insertOrUpdateInRecord(*face3, interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000083 strategy.afterReceiveInterest(*face3, interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070084
85 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070086 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000087 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
88 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070089
90 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070091 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +000092 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
93 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070094
95 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070096 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070097 Data& data1 = *data1p;
Junxiao Shia49a1ab2016-07-15 18:24:36 +000098 strategy.beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070099 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700100
101 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -0700102 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700103 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700104 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700105 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
106
Junxiao Shi9cff7792016-08-01 21:45:11 +0000107 pitEntry2->insertOrUpdateInRecord(*face3, interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000108 strategy.afterReceiveInterest(*face3, interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700109
110 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700111 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000112 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
113 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700114}
115
Junxiao Shicbb490a2014-08-13 12:24:24 -0700116BOOST_AUTO_TEST_CASE(Bug1853)
117{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700118 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000119 NccStrategyTester& strategy = choose<NccStrategyTester>(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();
Junxiao Shia6de4292016-07-12 02:08:10 +0000129 fib::Entry& fibEntry = *fib.insert(Name()).first;
130 fibEntry.addNextHop(*face1, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700131
Junxiao Shicbb490a2014-08-13 12:24:24 -0700132 Pit& pit = forwarder.getPit();
133
134 // first Interest: strategy follows routing and forwards to face1
135 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
136 interest1->setInterestLifetime(time::milliseconds(8000));
137 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
138
Junxiao Shi9cff7792016-08-01 21:45:11 +0000139 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000140 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700141
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700142 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000143 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
144 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700145
146 // face1 responds
147 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000148 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700149 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700150
151 // second Interest: bestFace is face1, nUpstreams becomes 0,
152 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
153 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
154 interest2->setInterestLifetime(time::milliseconds(8000));
155 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
156
Junxiao Shi9cff7792016-08-01 21:45:11 +0000157 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000158 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700159
160 // FIB entry is changed before doPropagate executes
Junxiao Shia6de4292016-07-12 02:08:10 +0000161 fibEntry.addNextHop(*face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700162 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700163}
164
Junxiao Shi82e7f582014-09-07 15:15:40 -0700165BOOST_AUTO_TEST_CASE(Bug1961)
166{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700167 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700168 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000169 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000170 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700171
172 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
173 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
174 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
175 forwarder.addFace(face1);
176 forwarder.addFace(face2);
177 forwarder.addFace(face3);
178
179 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000180 fib::Entry& fibEntry = *fib.insert(Name()).first;
181 fibEntry.addNextHop(*face1, 10);
182 fibEntry.addNextHop(*face2, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700183
Junxiao Shi82e7f582014-09-07 15:15:40 -0700184 Pit& pit = forwarder.getPit();
185
186 // first Interest: strategy forwards to face1 and face2
187 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
188 interest1->setInterestLifetime(time::milliseconds(2000));
189 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
190
Junxiao Shi9cff7792016-08-01 21:45:11 +0000191 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000192 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
193 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700194 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000195 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
196 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
197 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700198
199 // face1 responds
200 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000201 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700202 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700203 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700204 // face2 also responds
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000205 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700206 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700207
208 // second Interest: bestFace should be face 1
209 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
210 interest2->setInterestLifetime(time::milliseconds(2000));
211 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
212
Junxiao Shi9cff7792016-08-01 21:45:11 +0000213 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000214 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
215 limitedIo.run(3 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700216 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700217
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000218 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
219 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700220}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700221
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700222BOOST_AUTO_TEST_CASE(Bug1971)
223{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700224 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700225 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000226 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000227 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700228
229 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
230 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
231 forwarder.addFace(face1);
232 forwarder.addFace(face2);
233
234 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000235 fib::Entry& fibEntry = *fib.insert(Name()).first;
236 fibEntry.addNextHop(*face2, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700237
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700238 Pit& pit = forwarder.getPit();
239
240 // first Interest: strategy forwards to face2
241 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
242 interest1->setInterestLifetime(time::milliseconds(2000));
243 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
244
Junxiao Shi9cff7792016-08-01 21:45:11 +0000245 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000246 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
247 limitedIo.run(1 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700248 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000249 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
250 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700251
252 // face2 responds
253 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
254 data1->setFreshnessPeriod(time::milliseconds(5));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000255 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700256 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700257 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700258 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700259
260 // similar Interest: strategy should still forward it
Junxiao Shi9cff7792016-08-01 21:45:11 +0000261 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000262 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
263 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700264 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000265 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
266 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700267}
268
Junxiao Shi63162202015-01-14 22:27:33 -0700269BOOST_AUTO_TEST_CASE(Bug1998)
270{
271 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000272 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700273
274 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
275 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
276 forwarder.addFace(face1);
277 forwarder.addFace(face2);
278
279 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000280 fib::Entry& fibEntry = *fib.insert(Name()).first;
281 fibEntry.addNextHop(*face1, 10); // face1 is top-ranked nexthop
282 fibEntry.addNextHop(*face2, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700283
Junxiao Shi63162202015-01-14 22:27:33 -0700284 Pit& pit = forwarder.getPit();
285
286 // Interest comes from face1, which is sole downstream
287 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
288 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000289 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700290
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000291 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700292
293 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000294 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
295 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700296}
297
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700298BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
299BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
300{
301 /*
302 * /----------\
303 * | consumer |
304 * \----------/
305 * |
306 * |
307 * +---+ 5ms +---+
308 * | A |-------| B |
309 * +---+ +---+
310 * | |
311 * | 5ms | 15ms/5ms
312 * | |
313 * +---+ +---+
314 * | C |-------| D |
315 * +---+ 15ms +---+
316 * /5ms |
317 * |
318 * /----------\
319 * | producer |
320 * \----------/
321 */
322
323 TopologyTester topo;
324 TopologyNode nodeA = topo.addForwarder("A"),
325 nodeB = topo.addForwarder("B"),
326 nodeC = topo.addForwarder("C"),
327 nodeD = topo.addForwarder("D");
328
329 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
330 topo.setStrategy<NccStrategy>(node);
331 }
332
333 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
334 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
335 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
336 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
337
338 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
339 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
340 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
341 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
342
343 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
344 topo.addEchoProducer(producer->getClientFace());
345
346 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
347 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
348 time::milliseconds(100), 300);
349
Junxiao Shifc021862016-08-25 21:51:18 +0000350 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700351 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000352 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700353 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
354 };
355
356 // NccStrategy starts with an exploration period when the algorithm adjusts
357 // its prediction to converge near the path RTT.
358 bool isExplorationFinished = false;
359 const time::milliseconds TRUE_RTT1(40);
360 bool isLastPredictionUnder = true;
361 int nPredictionCrossings = 0;
362 for (int i = 0; i < 10000; ++i) {
363 this->advanceClocks(time::milliseconds(5));
364 auto meInfo = getMeInfo();
365 if (meInfo == nullptr) {
366 continue;
367 }
368
369 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
370 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
371 isLastPredictionUnder = !isLastPredictionUnder;
372 if (++nPredictionCrossings > 6) {
373 isExplorationFinished = true;
374 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
375 break;
376 }
377 }
378 }
379 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
380
381 // NccStrategy has selected one path as the best.
382 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
383 // However, this won't happen due to a weakness in NccStrategy.
384 // See http://redmine.named-data.net/issues/3411#note-4
385 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
386 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
387 linkCD->setDelay(time::milliseconds(5));
388 }
389 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
390 linkBD->setDelay(time::milliseconds(5));
391 }
392 else {
393 BOOST_FAIL("unexpected best face");
394 }
395
396 bool isNewBestChosen = false;
397 for (int i = 0; i < 10000; ++i) {
398 this->advanceClocks(time::milliseconds(5));
399 auto meInfo = getMeInfo();
400 if (meInfo == nullptr) {
401 continue;
402 }
403
404 if (meInfo->bestFace.lock() != bestFace1) {
405 isNewBestChosen = true;
406 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
407 break;
408 }
409 }
410 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
411}
412
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700413BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
414BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700415
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700416} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800417} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700418} // namespace nfd