blob: a10fc47ef8a1d7086559ce1fcd669ba02c69a7be [file] [log] [blame]
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi63162202015-01-14 22:27:33 -07003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070028#include "tests/daemon/face/dummy-face.hpp"
29#include "tests/limited-io.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070030
Junxiao Shid9ee45c2014-02-27 15:38:11 -070031#include "tests/test-common.hpp"
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070032
33namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080034namespace fw {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070036
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080037using namespace nfd::tests;
38
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070039BOOST_FIXTURE_TEST_SUITE(FwNccStrategy, UnitTestTimeFixture)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070040
41// NccStrategy is fairly complex.
42// The most important property is:
43// it remembers which upstream is the fastest to return Data,
44// and favors this upstream in subsequent Interests.
45BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
46{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070047 LimitedIo limitedIo(this);
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070048 Forwarder forwarder;
49 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
Alexander Afanasyevf6980282014-05-13 18:28:40 -070050 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070051 strategy->onAction.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();
61 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070062 fibEntry->addNextHop(face1, 10);
63 fibEntry->addNextHop(face2, 20);
64
Junxiao Shi7bb01512014-03-05 21:34:09 -070065 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
66 strategyChoice.install(strategy);
67 strategyChoice.insert(Name(), strategy->getName());
68
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070069 Pit& pit = forwarder.getPit();
70
71 // first Interest: strategy knows nothing and follows routing
Junxiao Shif3c07812014-03-11 21:48:49 -070072 shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070073 Interest& interest1 = *interest1p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070074 interest1.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070075 shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
76
77 pitEntry1->insertOrUpdateInRecord(face3, interest1);
78 strategy->afterReceiveInterest(*face3, interest1, fibEntry, pitEntry1);
79
80 // forwards to face1 because routing says it's best
Junxiao Shi15539102014-10-08 22:39:51 -070081 // (no io run here: afterReceiveInterest has already sent the Interest)
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070082 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 1);
83 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[0].get<1>(), face1);
84
85 // forwards to face2 because face1 doesn't respond
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070086 limitedIo.run(1, time::milliseconds(500), time::milliseconds(10));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070087 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 2);
88 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[1].get<1>(), face2);
89
90 // face2 responds
Junxiao Shif3c07812014-03-11 21:48:49 -070091 shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070092 Data& data1 = *data1p;
Junxiao Shi82e7f582014-09-07 15:15:40 -070093 strategy->beforeSatisfyInterest(pitEntry1, *face2, data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -070094 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070095
96 // second Interest: strategy knows face2 is best
Junxiao Shif3c07812014-03-11 21:48:49 -070097 shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -070098 Interest& interest2 = *interest2p;
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070099 interest2.setInterestLifetime(time::milliseconds(8000));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700100 shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
101
102 pitEntry2->insertOrUpdateInRecord(face3, interest2);
103 strategy->afterReceiveInterest(*face3, interest2, fibEntry, pitEntry2);
104
105 // forwards to face2 because it responds previously
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700106 this->advanceClocks(time::milliseconds(1));
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700107 BOOST_REQUIRE_GE(strategy->m_sendInterestHistory.size(), 3);
108 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[2].get<1>(), face2);
109}
110
Junxiao Shicbb490a2014-08-13 12:24:24 -0700111BOOST_AUTO_TEST_CASE(Bug1853)
112{
Junxiao Shicbb490a2014-08-13 12:24:24 -0700113 Forwarder forwarder;
114 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
115 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700116
117 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
118 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
119 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
120 forwarder.addFace(face1);
121 forwarder.addFace(face2);
122 forwarder.addFace(face3);
123
124 Fib& fib = forwarder.getFib();
125 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
126 fibEntry->addNextHop(face1, 10);
127
128 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
129 strategyChoice.install(strategy);
130 strategyChoice.insert(Name(), strategy->getName());
131
132 Pit& pit = forwarder.getPit();
133
134 // first Interest: strategy follows routing and forwards to face1
135 shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
136 interest1->setInterestLifetime(time::milliseconds(8000));
137 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
138
139 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
140 strategy->afterReceiveInterest(*face3, *interest1, fibEntry, pitEntry1);
141
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700142 this->advanceClocks(time::milliseconds(1));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700143 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 1);
144 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[0].get<1>(), face1);
145
146 // face1 responds
147 shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
Junxiao Shi82e7f582014-09-07 15:15:40 -0700148 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700149 this->advanceClocks(time::milliseconds(10), time::milliseconds(500));
Junxiao Shicbb490a2014-08-13 12:24:24 -0700150
151 // second Interest: bestFace is face1, nUpstreams becomes 0,
152 // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
153 shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
154 interest2->setInterestLifetime(time::milliseconds(8000));
155 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
156
157 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
158 strategy->afterReceiveInterest(*face3, *interest2, fibEntry, pitEntry2);
159
160 // FIB entry is changed before doPropagate executes
161 fibEntry->addNextHop(face2, 20);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700162 this->advanceClocks(time::milliseconds(10), time::milliseconds(1000));// should not crash
Junxiao Shicbb490a2014-08-13 12:24:24 -0700163}
164
Junxiao Shi82e7f582014-09-07 15:15:40 -0700165BOOST_AUTO_TEST_CASE(Bug1961)
166{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700167 LimitedIo limitedIo(this);
Junxiao Shi82e7f582014-09-07 15:15:40 -0700168 Forwarder forwarder;
169 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
170 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700171 strategy->onAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700172
173 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
174 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
175 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
176 forwarder.addFace(face1);
177 forwarder.addFace(face2);
178 forwarder.addFace(face3);
179
180 Fib& fib = forwarder.getFib();
181 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
182 fibEntry->addNextHop(face1, 10);
183 fibEntry->addNextHop(face2, 20);
184
185 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
186 strategyChoice.install(strategy);
187 strategyChoice.insert(Name(), strategy->getName());
188
189 Pit& pit = forwarder.getPit();
190
191 // first Interest: strategy forwards to face1 and face2
192 shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
193 interest1->setInterestLifetime(time::milliseconds(2000));
194 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
195
196 pitEntry1->insertOrUpdateInRecord(face3, *interest1);
197 strategy->afterReceiveInterest(*face3, *interest1, fibEntry, pitEntry1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700198 limitedIo.run(2 - strategy->m_sendInterestHistory.size(),
199 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700200 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 2);
201 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[0].get<1>(), face1);
202 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[1].get<1>(), face2);
203
204 // face1 responds
205 shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
206 strategy->beforeSatisfyInterest(pitEntry1, *face1, *data1);
207 pitEntry1->deleteInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700208 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700209 // face2 also responds
210 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700211 this->advanceClocks(time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700212
213 // second Interest: bestFace should be face 1
214 shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
215 interest2->setInterestLifetime(time::milliseconds(2000));
216 shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
217
218 pitEntry2->insertOrUpdateInRecord(face3, *interest2);
219 strategy->afterReceiveInterest(*face3, *interest2, fibEntry, pitEntry2);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700220 limitedIo.run(3 - strategy->m_sendInterestHistory.size(),
221 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi82e7f582014-09-07 15:15:40 -0700222
223 BOOST_REQUIRE_GE(strategy->m_sendInterestHistory.size(), 3);
224 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[2].get<1>(), face1);
225}
Junxiao Shicbb490a2014-08-13 12:24:24 -0700226
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700227BOOST_AUTO_TEST_CASE(Bug1971)
228{
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700229 LimitedIo limitedIo(this);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700230 Forwarder forwarder;
231 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
232 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700233 strategy->onAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700234
235 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
236 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
237 forwarder.addFace(face1);
238 forwarder.addFace(face2);
239
240 Fib& fib = forwarder.getFib();
241 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
242 fibEntry->addNextHop(face2, 10);
243
244 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
245 strategyChoice.install(strategy);
246 strategyChoice.insert(Name(), strategy->getName());
247
248 Pit& pit = forwarder.getPit();
249
250 // first Interest: strategy forwards to face2
251 shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
252 interest1->setInterestLifetime(time::milliseconds(2000));
253 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
254
255 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
256 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700257 limitedIo.run(1 - strategy->m_sendInterestHistory.size(),
258 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700259 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 1);
260 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[0].get<1>(), face2);
261
262 // face2 responds
263 shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
264 data1->setFreshnessPeriod(time::milliseconds(5));
265 strategy->beforeSatisfyInterest(pitEntry1, *face2, *data1);
Junxiao Shib2bcbcd2014-11-08 09:30:28 -0700266 pitEntry1->deleteOutRecord(*face2);
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700267 pitEntry1->deleteInRecords();
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700268 this->advanceClocks(time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700269
270 // similar Interest: strategy should still forward it
271 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
272 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
Junxiao Shi3cb4fc62014-12-25 22:17:39 -0700273 limitedIo.run(2 - strategy->m_sendInterestHistory.size(),
274 time::milliseconds(2000), time::milliseconds(10));
Junxiao Shi8bfd56d2014-10-08 10:06:00 -0700275 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 2);
276 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[1].get<1>(), face2);
277}
278
Junxiao Shi63162202015-01-14 22:27:33 -0700279BOOST_AUTO_TEST_CASE(Bug1998)
280{
281 Forwarder forwarder;
282 typedef StrategyTester<fw::NccStrategy> NccStrategyTester;
283 shared_ptr<NccStrategyTester> strategy = make_shared<NccStrategyTester>(ref(forwarder));
284
285 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
286 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
287 forwarder.addFace(face1);
288 forwarder.addFace(face2);
289
290 Fib& fib = forwarder.getFib();
291 shared_ptr<fib::Entry> fibEntry = fib.insert(Name()).first;
292 fibEntry->addNextHop(face1, 10); // face1 is top-ranked nexthop
293 fibEntry->addNextHop(face2, 20);
294
295 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
296 strategyChoice.install(strategy);
297 strategyChoice.insert(Name(), strategy->getName());
298
299 Pit& pit = forwarder.getPit();
300
301 // Interest comes from face1, which is sole downstream
302 shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
303 shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
304 pitEntry1->insertOrUpdateInRecord(face1, *interest1);
305
306 strategy->afterReceiveInterest(*face1, *interest1, fibEntry, pitEntry1);
307
308 // Interest shall go to face2, not loop back to face1
309 BOOST_REQUIRE_EQUAL(strategy->m_sendInterestHistory.size(), 1);
310 BOOST_CHECK_EQUAL(strategy->m_sendInterestHistory[0].get<1>(), face2);
311}
312
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700313BOOST_AUTO_TEST_SUITE_END()
314
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700315} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800316} // namespace fw
Junxiao Shi0b5fbbb2014-02-20 15:54:03 -0700317} // namespace nfd