blob: 3c3f4d4895ab414e6c3b23f3de073e900ecdddc4 [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);
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040049 FaceTable faceTable;
50 Forwarder forwarder(faceTable);
Junxiao Shi890afe92016-12-15 14:34:34 +000051 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000052 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070053
54 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
55 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
56 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040057 faceTable.add(face1);
58 faceTable.add(face2);
59 faceTable.add(face3);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070060
61 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000062 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +000063 fib.addOrUpdateNextHop(fibEntry, *face1, 10);
64 fib.addOrUpdateNextHop(fibEntry, *face2, 20);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070065
66 Pit& pit = forwarder.getPit();
67
68 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070069 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070070 Interest& interest1 = *interest1p;
Davide Pesavento14e71f02019-03-28 17:35:25 -040071 interest1.setInterestLifetime(8_s);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070072 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
73
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +000074 pitEntry1->insertOrUpdateInRecord(*face3, interest1);
ashiqopuc7079482019-02-20 05:34:37 +000075 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest1, pitEntry1);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070076
77 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070078 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shia49a1ab2016-07-15 18:24:36 +000079 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
80 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070081
82 // forwards to face2 because face1 doesn't respond
Davide Pesavento14e71f02019-03-28 17:35:25 -040083 limitedIo.run(1, 500_ms, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000084 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
85 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070086
87 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070088 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070089 Data& data1 = *data1p;
ashiqopuc7079482019-02-20 05:34:37 +000090 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), data1);
Davide Pesavento14e71f02019-03-28 17:35:25 -040091 this->advanceClocks(10_ms, 500_ms);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070092
93 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070094 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070095 Interest& interest2 = *interest2p;
Davide Pesavento14e71f02019-03-28 17:35:25 -040096 interest2.setInterestLifetime(8_s);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070097 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
98
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +000099 pitEntry2->insertOrUpdateInRecord(*face3, interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000100 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest2, pitEntry2);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700101
102 // forwards to face2 because it responds previously
Davide Pesavento14e71f02019-03-28 17:35:25 -0400103 this->advanceClocks(1_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000104 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
105 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700106}
107
Junxiao Shicbb490a2014-08-13 12:24:24 -0700108BOOST_AUTO_TEST_CASE(Bug1853)
109{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400110 FaceTable faceTable;
111 Forwarder forwarder(faceTable);
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>();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400117 faceTable.add(face1);
118 faceTable.add(face2);
119 faceTable.add(face3);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700120
121 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000122 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000123 fib.addOrUpdateNextHop(fibEntry, *face1, 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");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400129 interest1->setInterestLifetime(8_s);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700130 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
131
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000132 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000133 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700134
Davide Pesavento14e71f02019-03-28 17:35:25 -0400135 this->advanceClocks(1_ms);
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);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400142 this->advanceClocks(10_ms, 500_ms);
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");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400147 interest2->setInterestLifetime(8_s);
Junxiao Shicbb490a2014-08-13 12:24:24 -0700148 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
149
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000150 pitEntry2->insertOrUpdateInRecord(*face3, *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
Ju Pand8315bf2019-07-31 06:59:07 +0000154 fib.addOrUpdateNextHop(fibEntry, *face2, 20);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400155 this->advanceClocks(10_ms, 1_s);// 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);
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400161 FaceTable faceTable;
162 Forwarder forwarder(faceTable);
Junxiao Shi890afe92016-12-15 14:34:34 +0000163 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000164 strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700165
166 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
167 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
168 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400169 faceTable.add(face1);
170 faceTable.add(face2);
171 faceTable.add(face3);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700172
173 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000174 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000175 fib.addOrUpdateNextHop(fibEntry, *face1, 10);
176 fib.addOrUpdateNextHop(fibEntry, *face2, 20);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700177
Junxiao Shi82e7f582014-09-07 15:15:40 -0700178 Pit& pit = forwarder.getPit();
179
180 // first Interest: strategy forwards to face1 and face2
181 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400182 interest1->setInterestLifetime(2_s);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700183 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
184
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000185 pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000186 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400187 limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
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();
Davide Pesavento14e71f02019-03-28 17:35:25 -0400196 this->advanceClocks(10_ms);
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);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400199 this->advanceClocks(10_ms);
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");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400203 interest2->setInterestLifetime(2_s);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700204 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
205
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000206 pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
ashiqopuc7079482019-02-20 05:34:37 +0000207 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400208 limitedIo.run(3 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700209
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000210 BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
211 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
Junxiao Shi82e7f582014-09-07 15:15:40 -0700212}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700213
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700214BOOST_AUTO_TEST_CASE(Bug1971)
215{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700216 LimitedIo limitedIo(this);
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400217 FaceTable faceTable;
218 Forwarder forwarder(faceTable);
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>();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400224 faceTable.add(face1);
225 faceTable.add(face2);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700226
227 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000228 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000229 fib.addOrUpdateNextHop(fibEntry, *face2, 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");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400235 interest1->setInterestLifetime(2_s);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700236 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
237
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000238 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000239 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400240 limitedIo.run(1 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000241 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
242 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700243
244 // face2 responds
245 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
Davide Pesavento14e71f02019-03-28 17:35:25 -0400246 data1->setFreshnessPeriod(5_ms);
ashiqopuc7079482019-02-20 05:34:37 +0000247 strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000248 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700249 pitEntry1->clearInRecords();
Davide Pesavento14e71f02019-03-28 17:35:25 -0400250 this->advanceClocks(10_ms);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700251
252 // similar Interest: strategy should still forward it
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000253 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
ashiqopuc7079482019-02-20 05:34:37 +0000254 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400255 limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000256 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
257 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700258}
259
Junxiao Shi63162202015-01-14 22:27:33 -0700260BOOST_AUTO_TEST_CASE(Bug1998)
261{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400262 FaceTable faceTable;
263 Forwarder forwarder(faceTable);
Junxiao Shi890afe92016-12-15 14:34:34 +0000264 NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
Junxiao Shi63162202015-01-14 22:27:33 -0700265
266 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
267 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400268 faceTable.add(face1);
269 faceTable.add(face2);
Junxiao Shi63162202015-01-14 22:27:33 -0700270
271 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000272 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000273 fib.addOrUpdateNextHop(fibEntry, *face1, 10); // face1 is top-ranked nexthop
274 fib.addOrUpdateNextHop(fibEntry, *face2, 20);
Junxiao Shi63162202015-01-14 22:27:33 -0700275
Junxiao Shi63162202015-01-14 22:27:33 -0700276 Pit& pit = forwarder.getPit();
277
278 // Interest comes from face1, which is sole downstream
279 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
280 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000281 pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi63162202015-01-14 22:27:33 -0700282
ashiqopuc7079482019-02-20 05:34:37 +0000283 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
Junxiao Shi63162202015-01-14 22:27:33 -0700284
285 // Interest shall go to face2, not loop back to face1
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000286 BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
287 BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
Junxiao Shi63162202015-01-14 22:27:33 -0700288}
289
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700290BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
291BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
292{
293 /*
294 * /----------\
295 * | consumer |
296 * \----------/
297 * |
298 * |
299 * +---+ 5ms +---+
300 * | A |-------| B |
301 * +---+ +---+
302 * | |
303 * | 5ms | 15ms/5ms
304 * | |
305 * +---+ +---+
306 * | C |-------| D |
307 * +---+ 15ms +---+
308 * /5ms |
309 * |
310 * /----------\
311 * | producer |
312 * \----------/
313 */
314
315 TopologyTester topo;
316 TopologyNode nodeA = topo.addForwarder("A"),
317 nodeB = topo.addForwarder("B"),
318 nodeC = topo.addForwarder("C"),
319 nodeD = topo.addForwarder("D");
320
321 for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
322 topo.setStrategy<NccStrategy>(node);
323 }
324
Davide Pesavento14e71f02019-03-28 17:35:25 -0400325 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 5_ms, {nodeA, nodeB}),
326 linkAC = topo.addLink("AC", 5_ms, {nodeA, nodeC}),
327 linkBD = topo.addLink("BD", 15_ms, {nodeB, nodeD}),
328 linkCD = topo.addLink("CD", 15_ms, {nodeC, nodeD});
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700329
330 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
331 topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
332 topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
333 topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
334
335 shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
336 topo.addEchoProducer(producer->getClientFace());
337
338 shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
339 topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
Davide Pesavento14e71f02019-03-28 17:35:25 -0400340 100_ms, 300);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700341
Junxiao Shifc021862016-08-25 21:51:18 +0000342 auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700343 Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
Junxiao Shi80f9fcd2016-07-23 02:48:36 +0000344 measurements::Entry* me = measurements.findExactMatch("ndn:/P");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700345 return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
346 };
347
348 // NccStrategy starts with an exploration period when the algorithm adjusts
349 // its prediction to converge near the path RTT.
350 bool isExplorationFinished = false;
351 const time::milliseconds TRUE_RTT1(40);
352 bool isLastPredictionUnder = true;
353 int nPredictionCrossings = 0;
354 for (int i = 0; i < 10000; ++i) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400355 this->advanceClocks(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700356 auto meInfo = getMeInfo();
357 if (meInfo == nullptr) {
358 continue;
359 }
360
361 if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
362 (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
363 isLastPredictionUnder = !isLastPredictionUnder;
364 if (++nPredictionCrossings > 6) {
365 isExplorationFinished = true;
366 BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
367 break;
368 }
369 }
370 }
Davide Pesavento14e71f02019-03-28 17:35:25 -0400371 BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration did not finish within 50s");
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700372
373 // NccStrategy has selected one path as the best.
374 // When we reduce the RTT of the other path, ideally it should be selected as the best face.
375 // However, this won't happen due to a weakness in NccStrategy.
Md Ashiqur Rahman6be93872019-08-07 01:25:31 +0000376 // See https://redmine.named-data.net/issues/3411#note-4
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700377 shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
378 if (bestFace1.get() == &linkAB->getFace(nodeA)) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400379 linkCD->setDelay(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700380 }
381 else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400382 linkBD->setDelay(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700383 }
384 else {
385 BOOST_FAIL("unexpected best face");
386 }
387
388 bool isNewBestChosen = false;
389 for (int i = 0; i < 10000; ++i) {
Davide Pesavento14e71f02019-03-28 17:35:25 -0400390 this->advanceClocks(5_ms);
Hila Ben Abraham39a79be2016-03-30 22:00:55 -0700391 auto meInfo = getMeInfo();
392 if (meInfo == nullptr) {
393 continue;
394 }
395
396 if (meInfo->bestFace.lock() != bestFace1) {
397 isNewBestChosen = true;
398 BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
399 break;
400 }
401 }
402 BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
403}
404
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700405BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
406BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700407
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700408} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800409} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700410} // namespace nfd