blob: 86238af773234a22586d56bbd9b25497ccbf67f7 [file] [log] [blame]
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
ashiqopu3ad49db2018-10-20 22:38:47 +00002/*
3 * Copyright (c) 2014-2019, 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"
Davide Pesavento3dade002019-03-19 11:29:56 -060027
28#include "tests/daemon/face/dummy-face.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070029#include "strategy-tester.hpp"
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070030#include "topology-tester.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070031
32namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080033namespace fw {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070034namespace tests {
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070035
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080036using namespace nfd::tests;
37
Junxiao Shi890afe92016-12-15 14:34:34 +000038typedef StrategyTester<NccStrategy> NccStrategyTester;
39NFD_REGISTER_STRATEGY(NccStrategyTester);
40
Junxiao Shi5e5e4452015-09-24 16:56:52 -070041BOOST_AUTO_TEST_SUITE(Fw)
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040042BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, GlobalIoTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070043
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070044BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
45{
Junxiao Shi18739c42016-12-22 08:03:00 +000046 // NccStrategy is fairly complex.
47 // The most important property is: it remembers which upstream is the fastest to return Data,
48 // and favors this upstream in subsequent Interests.
49
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070050 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070051 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +000052 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000053 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070054
55 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
56 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
57 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
58 forwarder.addFace(face1);
59 forwarder.addFace(face2);
60 forwarder.addFace(face3);
61
62 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000063 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +000064 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
65 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070066
67 Pit& pit = forwarder.getPit();
68
69 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070070 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070071 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070072 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
74
ashiqopud3ae85d2019-02-17 02:29:55 +000075 pitEntry1->insertOrUpdateInRecord(*face3, 0, interest1);
ashiqopuc7079482019-02-20 05:34:37 +000076 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070077
78 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070079 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000080 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
81 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070082
83 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070084 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +000085 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
86 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070087
88 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070089 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070090 Data& data1 = *data1p;
ashiqopuc7079482019-02-20 05:34:37 +000091 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070092 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070093
94 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070095 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070096 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070097 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070098 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
99
ashiqopud3ae85d2019-02-17 02:29:55 +0000100 pitEntry2->insertOrUpdateInRecord(*face3, 0, interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000101 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700102
103 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700104 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000105 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
106 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700107}
108
Junxiao Shicbb490a2014-08-13 12:24:24 -0700109BOOST_AUTO_TEST_CASE(Bug1853)
110{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700111 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000112 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700113
114 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
115 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
116 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
117 forwarder.addFace(face1);
118 forwarder.addFace(face2);
119 forwarder.addFace(face3);
120
121 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000122 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000123 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700124
Junxiao Shicbb490a2014-08-13 12:24:24 -0700125 Pit& pit = forwarder.getPit();
126
127 // first Interest: strategy follows routing and forwards to face1
128 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
129 interest1->setInterestLifetime(time::milliseconds(8000));
130 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
131
ashiqopud3ae85d2019-02-17 02:29:55 +0000132 pitEntry1->insertOrUpdateInRecord(*face3, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000133 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700134
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700135 this->advanceClocks(time::milliseconds(1));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000136 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
137 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700138
139 // face1 responds
140 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
ashiqopuc7079482019-02-20 05:34:37 +0000141 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700142 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700143
144 // second Interest: bestFace is face1, nUpstreams becomes 0,
145 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
146 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
147 interest2->setInterestLifetime(time::milliseconds(8000));
148 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
149
ashiqopud3ae85d2019-02-17 02:29:55 +0000150 pitEntry2->insertOrUpdateInRecord(*face3, 0, *interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000151 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700152
153 // FIB entry is changed before doPropagate executes
ashiqopu3ad49db2018-10-20 22:38:47 +0000154 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700155 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700156}
157
Junxiao Shi82e7f582014-09-07 15:15:40 -0700158BOOST_AUTO_TEST_CASE(Bug1961)
159{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700160 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700161 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000162 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000163 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700164
165 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
166 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
167 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
168 forwarder.addFace(face1);
169 forwarder.addFace(face2);
170 forwarder.addFace(face3);
171
172 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000173 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000174 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
175 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700176
Junxiao Shi82e7f582014-09-07 15:15:40 -0700177 Pit& pit = forwarder.getPit();
178
179 // first Interest: strategy forwards to face1 and face2
180 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
181 interest1->setInterestLifetime(time::milliseconds(2000));
182 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
183
ashiqopud3ae85d2019-02-17 02:29:55 +0000184 pitEntry1->insertOrUpdateInRecord(*face3, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000185 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000186 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700187 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000188 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
189 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
190 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700191
192 // face1 responds
193 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
ashiqopuc7079482019-02-20 05:34:37 +0000194 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700195 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700196 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700197 // face2 also responds
ashiqopuc7079482019-02-20 05:34:37 +0000198 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700199 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700200
201 // second Interest: bestFace should be face 1
202 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
203 interest2->setInterestLifetime(time::milliseconds(2000));
204 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
205
ashiqopud3ae85d2019-02-17 02:29:55 +0000206 pitEntry2->insertOrUpdateInRecord(*face3, 0, *interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000207 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000208 limitedIo.run(3 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700209 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700210
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000211 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
212 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700213}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700214
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700215BOOST_AUTO_TEST_CASE(Bug1971)
216{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700217 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700218 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000219 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000220 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700221
222 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
223 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
224 forwarder.addFace(face1);
225 forwarder.addFace(face2);
226
227 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000228 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000229 fibEntry.addOrUpdateNextHop(*face2, 0, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700230
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700231 Pit& pit = forwarder.getPit();
232
233 // first Interest: strategy forwards to face2
234 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
235 interest1->setInterestLifetime(time::milliseconds(2000));
236 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
237
ashiqopud3ae85d2019-02-17 02:29:55 +0000238 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000239 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000240 limitedIo.run(1 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700241 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000242 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
243 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700244
245 // face2 responds
246 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
247 data1->setFreshnessPeriod(time::milliseconds(5));
ashiqopuc7079482019-02-20 05:34:37 +0000248 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
ashiqopud3ae85d2019-02-17 02:29:55 +0000249 pitEntry1->deleteOutRecord(*face2, 0);
Junxiao Shi4846f372016-04-05 13:39:30 -0700250 pitEntry1->clearInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700251 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700252
253 // similar Interest: strategy should still forward it
ashiqopud3ae85d2019-02-17 02:29:55 +0000254 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000255 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000256 limitedIo.run(2 - strategy.sendInterestHistory.size(),
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700257 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000258 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
259 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700260}
261
Junxiao Shi63162202015-01-14 22:27:33 -0700262BOOST_AUTO_TEST_CASE(Bug1998)
263{
264 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000265 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700266
267 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
268 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
269 forwarder.addFace(face1);
270 forwarder.addFace(face2);
271
272 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000273 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000274 fibEntry.addOrUpdateNextHop(*face1, 0, 10); // face1 is top-ranked nexthop
275 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700276
Junxiao Shi63162202015-01-14 22:27:33 -0700277 Pit& pit = forwarder.getPit();
278
279 // Interest comes from face1, which is sole downstream
280 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
281 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
ashiqopud3ae85d2019-02-17 02:29:55 +0000282 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700283
ashiqopuc7079482019-02-20 05:34:37 +0000284 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700285
286 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000287 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
288 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700289}
290
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700291BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
292BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
293{
294 /*
295 * /----------\
296 * | consumer |
297 * \----------/
298 * |
299 * |
300 * +---+ 5ms +---+
301 * | A |-------| B |
302 * +---+ +---+
303 * | |
304 * | 5ms | 15ms/5ms
305 * | |
306 * +---+ +---+
307 * | C |-------| D |
308 * +---+ 15ms +---+
309 * /5ms |
310 * |
311 * /----------\
312 * | producer |
313 * \----------/
314 */
315
316 TopologyTester topo;
317 TopologyNode nodeA = topo.addForwarder("A"),
318 nodeB = topo.addForwarder("B"),
319 nodeC = topo.addForwarder("C"),
320 nodeD = topo.addForwarder("D");
321
322 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
323 topo.setStrategy<NccStrategy>(node);
324 }
325
326 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds( 5), {nodeA, nodeB}),
327 linkAC = topo.addLink("AC", time::milliseconds( 5), {nodeA, nodeC}),
328 linkBD = topo.addLink("BD", time::milliseconds(15), {nodeB, nodeD}),
329 linkCD = topo.addLink("CD", time::milliseconds(15), {nodeC, nodeD});
330
331 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
332 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
333 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
334 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
335
336 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
337 topo.addEchoProducer(producer->getClientFace());
338
339 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
340 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
341 time::milliseconds(100), 300);
342
Junxiao Shifc021862016-08-25 21:51:18 +0000343 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700344 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000345 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700346 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
347 };
348
349 // NccStrategy starts with an exploration period when the algorithm adjusts
350 // its prediction to converge near the path RTT.
351 bool isExplorationFinished = false;
352 const time::milliseconds TRUE_RTT1(40);
353 bool isLastPredictionUnder = true;
354 int nPredictionCrossings = 0;
355 for (int i = 0; i < 10000; ++i) {
356 this->advanceClocks(time::milliseconds(5));
357 auto meInfo = getMeInfo();
358 if (meInfo == nullptr) {
359 continue;
360 }
361
362 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
363 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
364 isLastPredictionUnder = !isLastPredictionUnder;
365 if (++nPredictionCrossings > 6) {
366 isExplorationFinished = true;
367 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
368 break;
369 }
370 }
371 }
372 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration does not finish in 50000ms");
373
374 // NccStrategy has selected one path as the best.
375 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
376 // However, this won't happen due to a weakness in NccStrategy.
ashiqopu3ad49db2018-10-20 22:38:47 +0000377 // See https://redmine.named-data.net/issues/3411#note-4
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700378 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
379 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
380 linkCD->setDelay(time::milliseconds(5));
381 }
382 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
383 linkBD->setDelay(time::milliseconds(5));
384 }
385 else {
386 BOOST_FAIL("unexpected best face");
387 }
388
389 bool isNewBestChosen = false;
390 for (int i = 0; i < 10000; ++i) {
391 this->advanceClocks(time::milliseconds(5));
392 auto meInfo = getMeInfo();
393 if (meInfo == nullptr) {
394 continue;
395 }
396
397 if (meInfo->bestFace.lock() != bestFace1) {
398 isNewBestChosen = true;
399 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
400 break;
401 }
402 }
403 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
404}
405
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700406BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
407BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700408
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700409} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800410} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700411} // namespace nfd