blob: d7172e313b6e05ba3cfe93dfb325a513706844cd [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
Davide Pesavento14e71f02019-03-28 17:35:25 -040036using NccStrategyTester = StrategyTester<NccStrategy>;
Junxiao Shi890afe92016-12-15 14:34:34 +000037NFD_REGISTER_STRATEGY(NccStrategyTester);
38
Junxiao Shi5e5e4452015-09-24 16:56:52 -070039BOOST_AUTO_TEST_SUITE(Fw)
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040040BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, GlobalIoTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070041
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070042BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
43{
Junxiao Shi18739c42016-12-22 08:03:00 +000044 // NccStrategy is fairly complex.
45 // The most important property is: it remembers which upstream is the fastest to return Data,
46 // and favors this upstream in subsequent Interests.
47
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070048 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070049 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +000050 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000051 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070052
53 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
54 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
55 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
56 forwarder.addFace(face1);
57 forwarder.addFace(face2);
58 forwarder.addFace(face3);
59
60 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000061 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +000062 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
63 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070064
65 Pit& pit = forwarder.getPit();
66
67 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070068 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070069 Interest& interest1 = *interest1p;
Davide Pesavento14e71f02019-03-28 17:35:25 -040070 interest1.setInterestLifetime(8_s);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070071 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
72
ashiqopud3ae85d2019-02-17 02:29:55 +000073 pitEntry1->insertOrUpdateInRecord(*face3, 0, interest1);
ashiqopuc7079482019-02-20 05:34:37 +000074 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070075
76 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070077 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000078 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
79 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070080
81 // forwards to face2 because face1 doesn't respond
Davide Pesavento14e71f02019-03-28 17:35:25 -040082 limitedIo.run(1, 500_ms, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000083 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
84 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070085
86 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070087 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070088 Data& data1 = *data1p;
ashiqopuc7079482019-02-20 05:34:37 +000089 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), data1);
Davide Pesavento14e71f02019-03-28 17:35:25 -040090 this->advanceClocks(10_ms, 500_ms);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070091
92 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070093 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070094 Interest& interest2 = *interest2p;
Davide Pesavento14e71f02019-03-28 17:35:25 -040095 interest2.setInterestLifetime(8_s);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070096 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
97
ashiqopud3ae85d2019-02-17 02:29:55 +000098 pitEntry2->insertOrUpdateInRecord(*face3, 0, interest2);
ashiqopuc7079482019-02-20 05:34:37 +000099 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700100
101 // forwards to face2 because it responds previously
Davide Pesavento14e71f02019-03-28 17:35:25 -0400102 this->advanceClocks(1_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000103 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
104 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700105}
106
Junxiao Shicbb490a2014-08-13 12:24:24 -0700107BOOST_AUTO_TEST_CASE(Bug1853)
108{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700109 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000110 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700111
112 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
113 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
114 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
115 forwarder.addFace(face1);
116 forwarder.addFace(face2);
117 forwarder.addFace(face3);
118
119 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000120 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000121 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700122
Junxiao Shicbb490a2014-08-13 12:24:24 -0700123 Pit& pit = forwarder.getPit();
124
125 // first Interest: strategy follows routing and forwards to face1
126 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400127 interest1->setInterestLifetime(8_s);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700128 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
129
ashiqopud3ae85d2019-02-17 02:29:55 +0000130 pitEntry1->insertOrUpdateInRecord(*face3, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000131 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700132
Davide Pesavento14e71f02019-03-28 17:35:25 -0400133 this->advanceClocks(1_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000134 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
135 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shicbb490a2014-08-13 12:24:24 -0700136
137 // face1 responds
138 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
ashiqopuc7079482019-02-20 05:34:37 +0000139 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400140 this->advanceClocks(10_ms, 500_ms);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700141
142 // second Interest: bestFace is face1, nUpstreams becomes 0,
143 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
144 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400145 interest2->setInterestLifetime(8_s);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700146 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
147
ashiqopud3ae85d2019-02-17 02:29:55 +0000148 pitEntry2->insertOrUpdateInRecord(*face3, 0, *interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000149 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700150
151 // FIB entry is changed before doPropagate executes
ashiqopu3ad49db2018-10-20 22:38:47 +0000152 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400153 this->advanceClocks(10_ms, 1_s);// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700154}
155
Junxiao Shi82e7f582014-09-07 15:15:40 -0700156BOOST_AUTO_TEST_CASE(Bug1961)
157{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700158 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700159 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000160 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000161 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700162
163 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
164 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
165 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
166 forwarder.addFace(face1);
167 forwarder.addFace(face2);
168 forwarder.addFace(face3);
169
170 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000171 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000172 fibEntry.addOrUpdateNextHop(*face1, 0, 10);
173 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700174
Junxiao Shi82e7f582014-09-07 15:15:40 -0700175 Pit& pit = forwarder.getPit();
176
177 // first Interest: strategy forwards to face1 and face2
178 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400179 interest1->setInterestLifetime(2_s);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700180 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
181
ashiqopud3ae85d2019-02-17 02:29:55 +0000182 pitEntry1->insertOrUpdateInRecord(*face3, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000183 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400184 limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000185 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
186 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
187 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700188
189 // face1 responds
190 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
ashiqopuc7079482019-02-20 05:34:37 +0000191 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700192 pitEntry1->clearInRecords();
Davide Pesavento14e71f02019-03-28 17:35:25 -0400193 this->advanceClocks(10_ms);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700194 // face2 also responds
ashiqopuc7079482019-02-20 05:34:37 +0000195 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400196 this->advanceClocks(10_ms);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700197
198 // second Interest: bestFace should be face 1
199 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400200 interest2->setInterestLifetime(2_s);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700201 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
202
ashiqopud3ae85d2019-02-17 02:29:55 +0000203 pitEntry2->insertOrUpdateInRecord(*face3, 0, *interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000204 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400205 limitedIo.run(3 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700206
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000207 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
208 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700209}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700210
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700211BOOST_AUTO_TEST_CASE(Bug1971)
212{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700213 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700214 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000215 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000216 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700217
218 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
219 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
220 forwarder.addFace(face1);
221 forwarder.addFace(face2);
222
223 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000224 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000225 fibEntry.addOrUpdateNextHop(*face2, 0, 10);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700226
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700227 Pit& pit = forwarder.getPit();
228
229 // first Interest: strategy forwards to face2
230 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400231 interest1->setInterestLifetime(2_s);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700232 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
233
ashiqopud3ae85d2019-02-17 02:29:55 +0000234 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000235 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400236 limitedIo.run(1 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000237 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
238 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700239
240 // face2 responds
241 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400242 data1->setFreshnessPeriod(5_ms);
ashiqopuc7079482019-02-20 05:34:37 +0000243 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
ashiqopud3ae85d2019-02-17 02:29:55 +0000244 pitEntry1->deleteOutRecord(*face2, 0);
Junxiao Shi4846f372016-04-05 13:39:30 -0700245 pitEntry1->clearInRecords();
Davide Pesavento14e71f02019-03-28 17:35:25 -0400246 this->advanceClocks(10_ms);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700247
248 // similar Interest: strategy should still forward it
ashiqopud3ae85d2019-02-17 02:29:55 +0000249 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000250 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400251 limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000252 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
253 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700254}
255
Junxiao Shi63162202015-01-14 22:27:33 -0700256BOOST_AUTO_TEST_CASE(Bug1998)
257{
258 Forwarder forwarder;
Junxiao Shi890afe92016-12-15 14:34:34 +0000259 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700260
261 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
262 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
263 forwarder.addFace(face1);
264 forwarder.addFace(face2);
265
266 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000267 fib::Entry& fibEntry = *fib.insert(Name()).first;
ashiqopu3ad49db2018-10-20 22:38:47 +0000268 fibEntry.addOrUpdateNextHop(*face1, 0, 10); // face1 is top-ranked nexthop
269 fibEntry.addOrUpdateNextHop(*face2, 0, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700270
Junxiao Shi63162202015-01-14 22:27:33 -0700271 Pit& pit = forwarder.getPit();
272
273 // Interest comes from face1, which is sole downstream
274 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
275 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
ashiqopud3ae85d2019-02-17 02:29:55 +0000276 pitEntry1->insertOrUpdateInRecord(*face1, 0, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700277
ashiqopuc7079482019-02-20 05:34:37 +0000278 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700279
280 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000281 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
282 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700283}
284
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700285BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
286BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
287{
288 /*
289 * /----------\
290 * | consumer |
291 * \----------/
292 * |
293 * |
294 * +---+ 5ms +---+
295 * | A |-------| B |
296 * +---+ +---+
297 * | |
298 * | 5ms | 15ms/5ms
299 * | |
300 * +---+ +---+
301 * | C |-------| D |
302 * +---+ 15ms +---+
303 * /5ms |
304 * |
305 * /----------\
306 * | producer |
307 * \----------/
308 */
309
310 TopologyTester topo;
311 TopologyNode nodeA = topo.addForwarder("A"),
312 nodeB = topo.addForwarder("B"),
313 nodeC = topo.addForwarder("C"),
314 nodeD = topo.addForwarder("D");
315
316 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
317 topo.setStrategy<NccStrategy>(node);
318 }
319
Davide Pesavento14e71f02019-03-28 17:35:25 -0400320 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 5_ms, {nodeA, nodeB}),
321 linkAC = topo.addLink("AC", 5_ms, {nodeA, nodeC}),
322 linkBD = topo.addLink("BD", 15_ms, {nodeB, nodeD}),
323 linkCD = topo.addLink("CD", 15_ms, {nodeC, nodeD});
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700324
325 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
326 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
327 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
328 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
329
330 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
331 topo.addEchoProducer(producer->getClientFace());
332
333 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
334 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
Davide Pesavento14e71f02019-03-28 17:35:25 -0400335 100_ms, 300);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700336
Junxiao Shifc021862016-08-25 21:51:18 +0000337 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700338 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000339 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700340 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
341 };
342
343 // NccStrategy starts with an exploration period when the algorithm adjusts
344 // its prediction to converge near the path RTT.
345 bool isExplorationFinished = false;
346 const time::milliseconds TRUE_RTT1(40);
347 bool isLastPredictionUnder = true;
348 int nPredictionCrossings = 0;
349 for (int i = 0; i < 10000; ++i) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400350 this->advanceClocks(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700351 auto meInfo = getMeInfo();
352 if (meInfo == nullptr) {
353 continue;
354 }
355
356 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
357 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
358 isLastPredictionUnder = !isLastPredictionUnder;
359 if (++nPredictionCrossings > 6) {
360 isExplorationFinished = true;
361 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
362 break;
363 }
364 }
365 }
Davide Pesavento14e71f02019-03-28 17:35:25 -0400366 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration did not finish within 50s");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700367
368 // NccStrategy has selected one path as the best.
369 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
370 // However, this won't happen due to a weakness in NccStrategy.
ashiqopu3ad49db2018-10-20 22:38:47 +0000371 // See https://redmine.named-data.net/issues/3411#note-4
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700372 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
373 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400374 linkCD->setDelay(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700375 }
376 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400377 linkBD->setDelay(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700378 }
379 else {
380 BOOST_FAIL("unexpected best face");
381 }
382
383 bool isNewBestChosen = false;
384 for (int i = 0; i < 10000; ++i) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400385 this->advanceClocks(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700386 auto meInfo = getMeInfo();
387 if (meInfo == nullptr) {
388 continue;
389 }
390
391 if (meInfo->bestFace.lock() != bestFace1) {
392 isNewBestChosen = true;
393 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
394 break;
395 }
396 }
397 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
398}
399
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700400BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
401BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700402
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700403} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800404} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700405} // namespace nfd