blob: bc617c740e8c52b58ca5e745c0bd482ef8e378e9 [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 Shi18739c42016-12-22 08:03:00 +000051BOOST_AUTO_TEST_CASE(InstanceName)
52{
53 Forwarder forwarder;
54 BOOST_REQUIRE(NccStrategy::getStrategyName().at(-1).isVersion());
55 BOOST_CHECK_EQUAL(
56 NccStrategy(forwarder, NccStrategy::getStrategyName().getPrefix(-1)).getInstanceName(),
57 NccStrategy::getStrategyName());
58 BOOST_CHECK_THROW(
59 NccStrategy(forwarder, Name(NccStrategy::getStrategyName()).append("param")),
60 std::invalid_argument);
61}
62
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070063BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
64{
Junxiao Shi18739c42016-12-22 08:03:00 +000065 // NccStrategy is fairly complex.
66 // The most important property is: it remembers which upstream is the fastest to return Data,
67 // and favors this upstream in subsequent Interests.
68
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070069 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070070 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +000071 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000072 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073
74 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
75 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
76 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
77 forwarder.addFace(face1);
78 forwarder.addFace(face2);
79 forwarder.addFace(face3);
80
81 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000082 fib::Entry& fibEntry = *fib.insert(Name()).first;
83 fibEntry.addNextHop(*face1, 10);
84 fibEntry.addNextHop(*face2, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070085
86 Pit& pit = forwarder.getPit();
87
88 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070089 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070090 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070091 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070092 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
93
Junxiao Shi9cff7792016-08-01 21:45:11 +000094 pitEntry1->insertOrUpdateInRecord(*face3, interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000095 strategy.afterReceiveInterest(*face3, interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070096
97 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070098 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000099 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
100 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700101
102 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700103 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000104 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
105 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700106
107 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -0700108 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700109 Data& data1 = *data1p;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000110 strategy.beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700111 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700112
113 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -0700114 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700115 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700116 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700117 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
118
Junxiao Shi9cff7792016-08-01 21:45:11 +0000119 pitEntry2->insertOrUpdateInRecord(*face3, interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000120 strategy.afterReceiveInterest(*face3, interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700121
122 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700123 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000124 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
125 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700126}
127
Junxiao Shicbb490a2014-08-13 12:24:24 -0700128BOOST_AUTO_TEST_CASE(Bug1853)
129{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700130 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000131 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700132
133 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
134 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
135 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
136 forwarder.addFace(face1);
137 forwarder.addFace(face2);
138 forwarder.addFace(face3);
139
140 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000141 fib::Entry& fibEntry = *fib.insert(Name()).first;
142 fibEntry.addNextHop(*face1, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700143
Junxiao Shicbb490a2014-08-13 12:24:24 -0700144 Pit& pit = forwarder.getPit();
145
146 // first Interest: strategy follows routing and forwards to face1
147 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
148 interest1->setInterestLifetime(time::milliseconds(8000));
149 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
150
Junxiao Shi9cff7792016-08-01 21:45:11 +0000151 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000152 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700153
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700154 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000155 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
156 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700157
158 // face1 responds
159 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000160 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700161 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700162
163 // second Interest: bestFace is face1, nUpstreams becomes 0,
164 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
165 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
166 interest2->setInterestLifetime(time::milliseconds(8000));
167 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
168
Junxiao Shi9cff7792016-08-01 21:45:11 +0000169 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000170 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700171
172 // FIB entry is changed before doPropagate executes
Junxiao Shia6de4292016-07-12 02:08:10 +0000173 fibEntry.addNextHop(*face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700174 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700175}
176
Junxiao Shi82e7f582014-09-07 15:15:40 -0700177BOOST_AUTO_TEST_CASE(Bug1961)
178{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700179 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700180 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000181 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000182 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700183
184 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
185 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
186 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
187 forwarder.addFace(face1);
188 forwarder.addFace(face2);
189 forwarder.addFace(face3);
190
191 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000192 fib::Entry& fibEntry = *fib.insert(Name()).first;
193 fibEntry.addNextHop(*face1, 10);
194 fibEntry.addNextHop(*face2, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700195
Junxiao Shi82e7f582014-09-07 15:15:40 -0700196 Pit& pit = forwarder.getPit();
197
198 // first Interest: strategy forwards to face1 and face2
199 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
200 interest1->setInterestLifetime(time::milliseconds(2000));
201 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
202
Junxiao Shi9cff7792016-08-01 21:45:11 +0000203 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000204 strategy.afterReceiveInterest(*face3, *interest1, pitEntry1);
205 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700206 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000207 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
208 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
209 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700210
211 // face1 responds
212 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000213 strategy.beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700214 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700215 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700216 // face2 also responds
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000217 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700218 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700219
220 // second Interest: bestFace should be face 1
221 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
222 interest2->setInterestLifetime(time::milliseconds(2000));
223 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
224
Junxiao Shi9cff7792016-08-01 21:45:11 +0000225 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000226 strategy.afterReceiveInterest(*face3, *interest2, pitEntry2);
227 limitedIo.run(3 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700228 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700229
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000230 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
231 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700232}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700233
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700234BOOST_AUTO_TEST_CASE(Bug1971)
235{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700236 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700237 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000238 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000239 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700240
241 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
242 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
243 forwarder.addFace(face1);
244 forwarder.addFace(face2);
245
246 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000247 fib::Entry& fibEntry = *fib.insert(Name()).first;
248 fibEntry.addNextHop(*face2, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700249
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700250 Pit& pit = forwarder.getPit();
251
252 // first Interest: strategy forwards to face2
253 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
254 interest1->setInterestLifetime(time::milliseconds(2000));
255 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
256
Junxiao Shi9cff7792016-08-01 21:45:11 +0000257 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000258 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
259 limitedIo.run(1 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700260 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000261 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
262 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700263
264 // face2 responds
265 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
266 data1->setFreshnessPeriod(time::milliseconds(5));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000267 strategy.beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700268 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700269 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700270 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700271
272 // similar Interest: strategy should still forward it
Junxiao Shi9cff7792016-08-01 21:45:11 +0000273 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000274 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
275 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700276 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000277 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
278 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700279}
280
Junxiao Shi63162202015-01-14 22:27:33 -0700281BOOST_AUTO_TEST_CASE(Bug1998)
282{
283 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000284 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700285
286 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
287 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
288 forwarder.addFace(face1);
289 forwarder.addFace(face2);
290
291 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000292 fib::Entry& fibEntry = *fib.insert(Name()).first;
293 fibEntry.addNextHop(*face1, 10); // face1 is top-ranked nexthop
294 fibEntry.addNextHop(*face2, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700295
Junxiao Shi63162202015-01-14 22:27:33 -0700296 Pit& pit = forwarder.getPit();
297
298 // Interest comes from face1, which is sole downstream
299 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
300 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000301 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700302
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000303 strategy.afterReceiveInterest(*face1, *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700304
305 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000306 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
307 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700308}
309
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700310BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
311BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
312{
313 /*
314 * /----------\
315 * | consumer |
316 * \----------/
317 * |
318 * |
319 * +---+ 5ms +---+
320 * | A |-------| B |
321 * +---+ +---+
322 * | |
323 * | 5ms | 15ms/5ms
324 * | |
325 * +---+ +---+
326 * | C |-------| D |
327 * +---+ 15ms +---+
328 * /5ms |
329 * |
330 * /----------\
331 * | producer |
332 * \----------/
333 */
334
335 TopologyTester topo;
336 TopologyNode nodeA = topo.addForwarder("A"),
337 nodeB = topo.addForwarder("B"),
338 nodeC = topo.addForwarder("C"),
339 nodeD = topo.addForwarder("D");
340
341 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
342 topo.setStrategy<NccStrategy>(node);
343 }
344
345 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
346 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
347 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
348 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
349
350 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
351 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
352 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
353 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
354
355 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
356 topo.addEchoProducer(producer->getClientFace());
357
358 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
359 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
360 time::milliseconds(100), 300);
361
Junxiao Shifc021862016-08-25 21:51:18 +0000362 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700363 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000364 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700365 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
366 };
367
368 // NccStrategy starts with an exploration period when the algorithm adjusts
369 // its prediction to converge near the path RTT.
370 bool isExplorationFinished = false;
371 const time::milliseconds TRUE_RTT1(40);
372 bool isLastPredictionUnder = true;
373 int nPredictionCrossings = 0;
374 for (int i = 0; i < 10000; ++i) {
375 this->advanceClocks(time::milliseconds(5));
376 auto meInfo = getMeInfo();
377 if (meInfo == nullptr) {
378 continue;
379 }
380
381 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
382 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
383 isLastPredictionUnder = !isLastPredictionUnder;
384 if (++nPredictionCrossings > 6) {
385 isExplorationFinished = true;
386 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
387 break;
388 }
389 }
390 }
391 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
392
393 // NccStrategy has selected one path as the best.
394 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
395 // However, this won't happen due to a weakness in NccStrategy.
396 // See http://redmine.named-data.net/issues/3411#note-4
397 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
398 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
399 linkCD->setDelay(time::milliseconds(5));
400 }
401 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
402 linkBD->setDelay(time::milliseconds(5));
403 }
404 else {
405 BOOST_FAIL("unexpected best face");
406 }
407
408 bool isNewBestChosen = false;
409 for (int i = 0; i < 10000; ++i) {
410 this->advanceClocks(time::milliseconds(5));
411 auto meInfo = getMeInfo();
412 if (meInfo == nullptr) {
413 continue;
414 }
415
416 if (meInfo->bestFace.lock() != bestFace1) {
417 isNewBestChosen = true;
418 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
419 break;
420 }
421 }
422 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
423}
424
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700425BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
426BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700427
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700428} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800429} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700430} // namespace nfd