blob: 2e9ee185aade3e4a83729dd3aa999bf8a31428a7 [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 Shi0b5fbbb2014-02-20 15:54:03 -070046BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
47{
Junxiao Shi18739c42016-12-22 08:03:00 +000048 // NccStrategy is fairly complex.
49 // The most important property is: it remembers which upstream is the fastest to return Data,
50 // and favors this upstream in subsequent Interests.
51
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070052 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070053 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +000054 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000055 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();
Junxiao Shia6de4292016-07-12 02:08:10 +000065 fib::Entry& fibEntry = *fib.insert(Name()).first;
66 fibEntry.addNextHop(*face1, 10);
67 fibEntry.addNextHop(*face2, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070068
69 Pit& pit = forwarder.getPit();
70
71 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070072 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070074 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070075 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
76
Junxiao Shi9cff7792016-08-01 21:45:11 +000077 pitEntry1->insertOrUpdateInRecord(*face3, interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000078 strategy.afterReceiveInterest(*face3, interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070079
80 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070081 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000082 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
83 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070084
85 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070086 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +000087 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
88 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070089
90 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070091 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070092 Data& data1 = *data1p;
Junxiao Shia49a1ab2016-07-15 18:24:36 +000093 strategy.beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070094 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070095
96 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070097 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070098 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070099 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700100 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
101
Junxiao Shi9cff7792016-08-01 21:45:11 +0000102 pitEntry2->insertOrUpdateInRecord(*face3, interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000103 strategy.afterReceiveInterest(*face3, interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700104
105 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700106 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000107 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
108 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700109}
110
Junxiao Shicbb490a2014-08-13 12:24:24 -0700111BOOST_AUTO_TEST_CASE(Bug1853)
112{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700113 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000114 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700115
116 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
117 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
118 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
119 forwarder.addFace(face1);
120 forwarder.addFace(face2);
121 forwarder.addFace(face3);
122
123 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000124 fib::Entry& fibEntry = *fib.insert(Name()).first;
125 fibEntry.addNextHop(*face1, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700126
Junxiao Shicbb490a2014-08-13 12:24:24 -0700127 Pit& pit = forwarder.getPit();
128
129 // first Interest: strategy follows routing and forwards to face1
130 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
131 interest1->setInterestLifetime(time::milliseconds(8000));
132 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
133
Junxiao Shi9cff7792016-08-01 21:45:11 +0000134 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000135 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700136
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700137 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000138 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
139 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700140
141 // face1 responds
142 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000143 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700144 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700145
146 // second Interest: bestFace is face1, nUpstreams becomes 0,
147 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
148 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
149 interest2->setInterestLifetime(time::milliseconds(8000));
150 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
151
Junxiao Shi9cff7792016-08-01 21:45:11 +0000152 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000153 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700154
155 // FIB entry is changed before doPropagate executes
Junxiao Shia6de4292016-07-12 02:08:10 +0000156 fibEntry.addNextHop(*face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700157 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700158}
159
Junxiao Shi82e7f582014-09-07 15:15:40 -0700160BOOST_AUTO_TEST_CASE(Bug1961)
161{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700162 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700163 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000164 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000165 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700166
167 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
168 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
169 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
170 forwarder.addFace(face1);
171 forwarder.addFace(face2);
172 forwarder.addFace(face3);
173
174 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000175 fib::Entry& fibEntry = *fib.insert(Name()).first;
176 fibEntry.addNextHop(*face1, 10);
177 fibEntry.addNextHop(*face2, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700178
Junxiao Shi82e7f582014-09-07 15:15:40 -0700179 Pit& pit = forwarder.getPit();
180
181 // first Interest: strategy forwards to face1 and face2
182 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
183 interest1->setInterestLifetime(time::milliseconds(2000));
184 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
185
Junxiao Shi9cff7792016-08-01 21:45:11 +0000186 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000187 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
188 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700189 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000190 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
191 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
192 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700193
194 // face1 responds
195 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000196 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700197 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700198 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700199 // face2 also responds
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000200 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700201 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700202
203 // second Interest: bestFace should be face 1
204 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
205 interest2->setInterestLifetime(time::milliseconds(2000));
206 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
207
Junxiao Shi9cff7792016-08-01 21:45:11 +0000208 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000209 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
210 limitedIo.run(3 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700211 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700212
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000213 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
214 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700215}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700216
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700217BOOST_AUTO_TEST_CASE(Bug1971)
218{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700219 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700220 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000221 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000222 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700223
224 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
225 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
226 forwarder.addFace(face1);
227 forwarder.addFace(face2);
228
229 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000230 fib::Entry& fibEntry = *fib.insert(Name()).first;
231 fibEntry.addNextHop(*face2, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700232
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700233 Pit& pit = forwarder.getPit();
234
235 // first Interest: strategy forwards to face2
236 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
237 interest1->setInterestLifetime(time::milliseconds(2000));
238 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
239
Junxiao Shi9cff7792016-08-01 21:45:11 +0000240 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000241 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
242 limitedIo.run(1 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700243 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000244 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
245 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700246
247 // face2 responds
248 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
249 data1->setFreshnessPeriod(time::milliseconds(5));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000250 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700251 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700252 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700253 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700254
255 // similar Interest: strategy should still forward it
Junxiao Shi9cff7792016-08-01 21:45:11 +0000256 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000257 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
258 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700259 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000260 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
261 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700262}
263
Junxiao Shi63162202015-01-14 22:27:33 -0700264BOOST_AUTO_TEST_CASE(Bug1998)
265{
266 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000267 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700268
269 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
270 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
271 forwarder.addFace(face1);
272 forwarder.addFace(face2);
273
274 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000275 fib::Entry& fibEntry = *fib.insert(Name()).first;
276 fibEntry.addNextHop(*face1, 10); // face1 is top-ranked nexthop
277 fibEntry.addNextHop(*face2, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700278
Junxiao Shi63162202015-01-14 22:27:33 -0700279 Pit& pit = forwarder.getPit();
280
281 // Interest comes from face1, which is sole downstream
282 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
283 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000284 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700285
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000286 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700287
288 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000289 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
290 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700291}
292
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700293BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
294BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
295{
296 /*
297 * /----------\
298 * | consumer |
299 * \----------/
300 * |
301 * |
302 * +---+ 5ms +---+
303 * | A |-------| B |
304 * +---+ +---+
305 * | |
306 * | 5ms | 15ms/5ms
307 * | |
308 * +---+ +---+
309 * | C |-------| D |
310 * +---+ 15ms +---+
311 * /5ms |
312 * |
313 * /----------\
314 * | producer |
315 * \----------/
316 */
317
318 TopologyTester topo;
319 TopologyNode nodeA = topo.addForwarder("A"),
320 nodeB = topo.addForwarder("B"),
321 nodeC = topo.addForwarder("C"),
322 nodeD = topo.addForwarder("D");
323
324 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
325 topo.setStrategy<NccStrategy>(node);
326 }
327
328 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
329 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
330 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
331 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
332
333 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
334 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
335 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
336 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
337
338 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
339 topo.addEchoProducer(producer->getClientFace());
340
341 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
342 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
343 time::milliseconds(100), 300);
344
Junxiao Shifc021862016-08-25 21:51:18 +0000345 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700346 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000347 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700348 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
349 };
350
351 // NccStrategy starts with an exploration period when the algorithm adjusts
352 // its prediction to converge near the path RTT.
353 bool isExplorationFinished = false;
354 const time::milliseconds TRUE_RTT1(40);
355 bool isLastPredictionUnder = true;
356 int nPredictionCrossings = 0;
357 for (int i = 0; i < 10000; ++i) {
358 this->advanceClocks(time::milliseconds(5));
359 auto meInfo = getMeInfo();
360 if (meInfo == nullptr) {
361 continue;
362 }
363
364 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
365 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
366 isLastPredictionUnder = !isLastPredictionUnder;
367 if (++nPredictionCrossings > 6) {
368 isExplorationFinished = true;
369 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
370 break;
371 }
372 }
373 }
374 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
375
376 // NccStrategy has selected one path as the best.
377 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
378 // However, this won't happen due to a weakness in NccStrategy.
379 // See http://redmine.named-data.net/issues/3411#note-4
380 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
381 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
382 linkCD->setDelay(time::milliseconds(5));
383 }
384 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
385 linkBD->setDelay(time::milliseconds(5));
386 }
387 else {
388 BOOST_FAIL("unexpected best face");
389 }
390
391 bool isNewBestChosen = false;
392 for (int i = 0; i < 10000; ++i) {
393 this->advanceClocks(time::milliseconds(5));
394 auto meInfo = getMeInfo();
395 if (meInfo == nullptr) {
396 continue;
397 }
398
399 if (meInfo->bestFace.lock() != bestFace1) {
400 isNewBestChosen = true;
401 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
402 break;
403 }
404 }
405 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
406}
407
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700408BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
409BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700410
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700411} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800412} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700413} // namespace nfd