blob: 67bce49bf1b7811a97848392326c11f7c9b1d4db [file] [log] [blame]
Junxiao Shi8c8d2182014-01-30 22:33:00 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * 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 Shi8c8d2182014-01-30 22:33:00 -070025
26#include "fw/forwarder.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070027#include "tests/daemon/face/dummy-face.hpp"
Junxiao Shi5e5e4452015-09-24 16:56:52 -070028#include "tests/daemon/face/dummy-lp-face.hpp"
29#include "face/lp-face-wrapper.hpp"
Junxiao Shif3c07812014-03-11 21:48:49 -070030#include "dummy-strategy.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070031
Junxiao Shid9ee45c2014-02-27 15:38:11 -070032#include "tests/test-common.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070033#include "tests/limited-io.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070034
35namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070036namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070037
Junxiao Shi0355e9f2015-09-02 07:24:53 -070038BOOST_AUTO_TEST_SUITE(Fw)
39BOOST_FIXTURE_TEST_SUITE(TestForwarder, BaseFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070040
Junxiao Shi8c8d2182014-01-30 22:33:00 -070041BOOST_AUTO_TEST_CASE(SimpleExchange)
42{
Junxiao Shi75ab6b72014-11-30 01:01:05 -070043 LimitedIo limitedIo;
44 auto afterOp = bind(&LimitedIo::afterOp, &limitedIo);;
Junxiao Shic041ca32014-02-25 20:01:15 -070045 Forwarder forwarder;
46
Junxiao Shi8c8d2182014-01-30 22:33:00 -070047 Name nameA ("ndn:/A");
48 Name nameAB ("ndn:/A/B");
49 Name nameABC("ndn:/A/B/C");
Junxiao Shif3c07812014-03-11 21:48:49 -070050 shared_ptr<Interest> interestAB = makeInterest(nameAB);
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070051 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shif3c07812014-03-11 21:48:49 -070052 shared_ptr<Data> dataABC = makeData(nameABC);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070053
Junxiao Shid9ee45c2014-02-27 15:38:11 -070054 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
55 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
Junxiao Shic099ddb2014-12-25 20:53:20 -070056 face1->afterSend.connect(afterOp);
57 face2->afterSend.connect(afterOp);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070058 forwarder.addFace(face1);
59 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070060
Junxiao Shi8c8d2182014-01-30 22:33:00 -070061 Fib& fib = forwarder.getFib();
Junxiao Shi6e694322014-04-03 10:27:13 -070062 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
Junxiao Shi8c8d2182014-01-30 22:33:00 -070063 fibEntry->addNextHop(face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070064
Junxiao Shida93f1f2015-11-11 06:13:16 -070065 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
66 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070067 g_io.post([&] { face1->receiveInterest(*interestAB); });
68 BOOST_CHECK_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070069 BOOST_REQUIRE_EQUAL(face2->m_sentInterests.size(), 1);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070070 BOOST_CHECK_EQUAL(face2->m_sentInterests[0].getName(), nameAB);
Junxiao Shi0de23a22015-12-03 20:07:02 +000071 BOOST_REQUIRE(face2->m_sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
72 BOOST_CHECK_EQUAL(*face2->m_sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070073 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
74 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070075
Junxiao Shida93f1f2015-11-11 06:13:16 -070076 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
77 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070078 g_io.post([&] { face2->receiveData(*dataABC); });
79 BOOST_CHECK_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070080 BOOST_REQUIRE_EQUAL(face1->m_sentDatas.size(), 1);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070081 BOOST_CHECK_EQUAL(face1->m_sentDatas[0].getName(), nameABC);
Junxiao Shi0de23a22015-12-03 20:07:02 +000082 BOOST_REQUIRE(face1->m_sentDatas[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
83 BOOST_CHECK_EQUAL(*face1->m_sentDatas[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070084 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
85 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070086}
87
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070088BOOST_AUTO_TEST_CASE(CsMatched)
89{
90 LimitedIo limitedIo;
91 Forwarder forwarder;
92
93 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
94 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
95 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
96 forwarder.addFace(face1);
97 forwarder.addFace(face2);
98 forwarder.addFace(face3);
99
100 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
101 interestA->setInterestLifetime(time::seconds(4));
102 shared_ptr<Data> dataA = makeData("ndn:/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +0000103 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700104
105 Fib& fib = forwarder.getFib();
106 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
107 fibEntry->addNextHop(face2, 0);
108
109 Pit& pit = forwarder.getPit();
110 BOOST_CHECK_EQUAL(pit.size(), 0);
111
112 Cs& cs = forwarder.getCs();
113 BOOST_REQUIRE(cs.insert(*dataA));
114
115 face1->receiveInterest(*interestA);
116 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
117 // Interest matching ContentStore should not be forwarded
118 BOOST_REQUIRE_EQUAL(face2->m_sentInterests.size(), 0);
119
120 BOOST_REQUIRE_EQUAL(face1->m_sentDatas.size(), 1);
121 // IncomingFaceId field should be reset to represent CS
Junxiao Shi0de23a22015-12-03 20:07:02 +0000122 BOOST_REQUIRE(face1->m_sentDatas[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
123 BOOST_CHECK_EQUAL(*face1->m_sentDatas[0].getTag<lp::IncomingFaceIdTag>(), FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700124
125 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(500));
126 // PIT entry should not be left behind
127 BOOST_CHECK_EQUAL(pit.size(), 0);
128}
129
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700130class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700131{
132public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700133 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700134 {
135 }
136
137 virtual void
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700138 onDataUnsolicited(Face& inFace, const Data& data) DECL_OVERRIDE
Junxiao Shi88884492014-02-15 15:57:43 -0700139 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700140 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700141 }
142
143protected:
144 virtual void
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700145 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) DECL_OVERRIDE
Junxiao Shi88884492014-02-15 15:57:43 -0700146 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700147 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700148 }
149
150public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700151 int dispatchToStrategy_count;
152 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700153};
154
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700155BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700156{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700157 ScopeLocalhostIncomingTestForwarder forwarder;
158 shared_ptr<Face> face1 = make_shared<DummyLocalFace>();
159 shared_ptr<Face> face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700160 forwarder.addFace(face1);
161 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700162
Junxiao Shi88884492014-02-15 15:57:43 -0700163 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700164 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700165 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800166 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700167 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700168
Junxiao Shi88884492014-02-15 15:57:43 -0700169 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700170 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700171 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800172 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700173 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700174
Junxiao Shi88884492014-02-15 15:57:43 -0700175 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700176 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700177 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800178 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700179 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700180
Junxiao Shi88884492014-02-15 15:57:43 -0700181 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700182 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700183 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800184 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700185 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700186
Junxiao Shi88884492014-02-15 15:57:43 -0700187 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700188 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700189 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800190 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700191 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700192
193 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700194 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700195 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800196 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700197 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700198
Junxiao Shi88884492014-02-15 15:57:43 -0700199 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700200 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700201 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800202 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700203 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700204
205 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700206 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700207 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800208 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700209 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700210}
211
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700212BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
213{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700214 Forwarder forwarder;
215 shared_ptr<DummyLocalFace> face1 = make_shared<DummyLocalFace>();
216 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
217 shared_ptr<Face> face3 = make_shared<DummyLocalFace>();
218 forwarder.addFace(face1);
219 forwarder.addFace(face2);
220 forwarder.addFace(face3);
221 Pit& pit = forwarder.getPit();
222
223 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700224 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
225 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
226 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700227 face1->m_sentInterests.clear();
228 forwarder.onOutgoingInterest(pitA1, *face1);
229 BOOST_CHECK_EQUAL(face1->m_sentInterests.size(), 1);
230
231 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700232 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
233 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
234 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700235 face2->m_sentInterests.clear();
236 forwarder.onOutgoingInterest(pitA2, *face2);
237 BOOST_CHECK_EQUAL(face2->m_sentInterests.size(), 0);
238
239 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700240 shared_ptr<Interest> interestA3 = makeInterest("/A3");
241 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
242 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700243 face1->m_sentInterests.clear();
244 forwarder.onOutgoingInterest(pitA3, *face1);
245 BOOST_CHECK_EQUAL(face1->m_sentInterests.size(), 1);
246
247 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700248 shared_ptr<Interest> interestA4 = makeInterest("/A4");
249 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
250 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700251 face2->m_sentInterests.clear();
252 forwarder.onOutgoingInterest(pitA4, *face2);
253 BOOST_CHECK_EQUAL(face2->m_sentInterests.size(), 1);
254
255 // local face, /localhost: OK
256 face1->m_sentDatas.clear();
257 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
258 BOOST_CHECK_EQUAL(face1->m_sentDatas.size(), 1);
259
260 // non-local face, /localhost: OK
261 face2->m_sentDatas.clear();
262 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
263 BOOST_CHECK_EQUAL(face2->m_sentDatas.size(), 0);
264
265 // local face, non-/localhost: OK
266 face1->m_sentDatas.clear();
267 forwarder.onOutgoingData(Data("/B3"), *face1);
268 BOOST_CHECK_EQUAL(face1->m_sentDatas.size(), 1);
269
270 // non-local face, non-/localhost: OK
271 face2->m_sentDatas.clear();
272 forwarder.onOutgoingData(Data("/B4"), *face2);
273 BOOST_CHECK_EQUAL(face2->m_sentDatas.size(), 1);
274}
275
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700276BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
277{
278 Forwarder forwarder;
279 shared_ptr<DummyLocalFace> face1 = make_shared<DummyLocalFace>();
280 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
281 shared_ptr<DummyLocalFace> face3 = make_shared<DummyLocalFace>();
282 shared_ptr<DummyFace> face4 = make_shared<DummyFace>();
283 forwarder.addFace(face1);
284 forwarder.addFace(face2);
285 forwarder.addFace(face3);
286 forwarder.addFace(face4);
287 Pit& pit = forwarder.getPit();
288
289 // from local face, to local face: OK
290 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
291 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
292 pit1->insertOrUpdateInRecord(face1, *interest1);
293 face3->m_sentInterests.clear();
294 forwarder.onOutgoingInterest(pit1, *face3);
295 BOOST_CHECK_EQUAL(face3->m_sentInterests.size(), 1);
296
297 // from non-local face, to local face: OK
298 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
299 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
300 pit2->insertOrUpdateInRecord(face2, *interest2);
301 face3->m_sentInterests.clear();
302 forwarder.onOutgoingInterest(pit2, *face3);
303 BOOST_CHECK_EQUAL(face3->m_sentInterests.size(), 1);
304
305 // from local face, to non-local face: OK
306 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
307 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
308 pit3->insertOrUpdateInRecord(face1, *interest3);
309 face4->m_sentInterests.clear();
310 forwarder.onOutgoingInterest(pit3, *face4);
311 BOOST_CHECK_EQUAL(face4->m_sentInterests.size(), 1);
312
313 // from non-local face, to non-local face: violate
314 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
315 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
316 pit4->insertOrUpdateInRecord(face2, *interest4);
317 face4->m_sentInterests.clear();
318 forwarder.onOutgoingInterest(pit4, *face4);
319 BOOST_CHECK_EQUAL(face4->m_sentInterests.size(), 0);
320
321 // from local face and non-local face, to local face: OK
322 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
323 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
324 pit5->insertOrUpdateInRecord(face1, *interest5);
325 pit5->insertOrUpdateInRecord(face2, *interest5);
326 face3->m_sentInterests.clear();
327 forwarder.onOutgoingInterest(pit5, *face3);
328 BOOST_CHECK_EQUAL(face3->m_sentInterests.size(), 1);
329
330 // from local face and non-local face, to non-local face: OK
331 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
332 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
333 pit6->insertOrUpdateInRecord(face1, *interest6);
334 pit6->insertOrUpdateInRecord(face2, *interest6);
335 face4->m_sentInterests.clear();
336 forwarder.onOutgoingInterest(pit6, *face4);
337 BOOST_CHECK_EQUAL(face4->m_sentInterests.size(), 1);
338}
339
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700340BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700341{
342 LimitedIo limitedIo;
343 Forwarder forwarder;
344 shared_ptr<Face> face1 = make_shared<DummyFace>();
345 shared_ptr<Face> face2 = make_shared<DummyFace>();
346 forwarder.addFace(face1);
347 forwarder.addFace(face2);
348
349 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
350 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700351 ref(forwarder), "ndn:/strategyP");
Junxiao Shif3c07812014-03-11 21:48:49 -0700352 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700353 ref(forwarder), "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700354 strategyChoice.install(strategyP);
355 strategyChoice.install(strategyQ);
356 strategyChoice.insert("ndn:/" , strategyP->getName());
357 strategyChoice.insert("ndn:/B", strategyQ->getName());
358
359 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700360 strategyP->afterReceiveInterest_count = 0;
361 strategyP->interestOutFace = face2;
362 forwarder.startProcessInterest(*face1, *interest1);
363 BOOST_CHECK_EQUAL(strategyP->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700364
365 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700366 strategyQ->afterReceiveInterest_count = 0;
367 strategyQ->interestOutFace = face2;
368 forwarder.startProcessInterest(*face1, *interest2);
369 BOOST_CHECK_EQUAL(strategyQ->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700370
371 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
372
373 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700374 strategyP->beforeSatisfyInterest_count = 0;
375 forwarder.startProcessData(*face2, *data1);
376 BOOST_CHECK_EQUAL(strategyP->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700377
378 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700379 strategyQ->beforeSatisfyInterest_count = 0;
380 forwarder.startProcessData(*face2, *data2);
381 BOOST_CHECK_EQUAL(strategyQ->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700382
383 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700384 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700385 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700386 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700387 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700388 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700389
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700390 strategyP->beforeExpirePendingInterest_count = 0;
391 strategyQ->beforeExpirePendingInterest_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700392 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(100));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700393 BOOST_CHECK_EQUAL(strategyP->beforeExpirePendingInterest_count, 1);
394 BOOST_CHECK_EQUAL(strategyQ->beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700395}
396
Junxiao Shida006f52014-05-16 11:18:00 -0700397BOOST_AUTO_TEST_CASE(IncomingData)
398{
399 LimitedIo limitedIo;
400 Forwarder forwarder;
401 shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
402 shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
403 shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
404 shared_ptr<DummyFace> face4 = make_shared<DummyFace>();
405 forwarder.addFace(face1);
406 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700407 forwarder.addFace(face3);
408 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700409
410 Pit& pit = forwarder.getPit();
411 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
412 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
413 pit0->insertOrUpdateInRecord(face1, *interest0);
414 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
415 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
416 pitA->insertOrUpdateInRecord(face1, *interestA);
417 pitA->insertOrUpdateInRecord(face2, *interestA);
418 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
419 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
420 pitC->insertOrUpdateInRecord(face3, *interestC);
421 pitC->insertOrUpdateInRecord(face4, *interestC);
422
423 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
424 forwarder.onIncomingData(*face3, *dataD);
425 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
426
427 BOOST_CHECK_EQUAL(face1->m_sentDatas.size(), 1);
428 BOOST_CHECK_EQUAL(face2->m_sentDatas.size(), 1);
429 BOOST_CHECK_EQUAL(face3->m_sentDatas.size(), 0);
430 BOOST_CHECK_EQUAL(face4->m_sentDatas.size(), 1);
431}
432
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700433BOOST_AUTO_TEST_CASE(IncomingNack)
434{
435 Forwarder forwarder;
436 auto face1 = make_shared<DummyFace>();
437 auto face2 = make_shared<DummyFace>();
438 auto face3 = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>(
439 "dummy://", "dummy://",
440 ndn::nfd::FACE_SCOPE_NON_LOCAL,
441 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
442 ndn::nfd::LINK_TYPE_MULTI_ACCESS));
443 forwarder.addFace(face1);
444 forwarder.addFace(face2);
445 forwarder.addFace(face3);
446
447 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
448 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
449 ref(forwarder), "ndn:/strategyP");
450 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
451 ref(forwarder), "ndn:/strategyQ");
452 strategyChoice.install(strategyP);
453 strategyChoice.install(strategyQ);
454 strategyChoice.insert("ndn:/" , strategyP->getName());
455 strategyChoice.insert("ndn:/B", strategyQ->getName());
456
457 Pit& pit = forwarder.getPit();
458
459 // dispatch to the correct strategy
460 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
461 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
462 pit1->insertOrUpdateOutRecord(face1, *interest1);
463 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
464 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
465 pit2->insertOrUpdateOutRecord(face1, *interest2);
466
467 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
468 strategyP->afterReceiveNack_count = 0;
469 strategyQ->afterReceiveNack_count = 0;
470 forwarder.onIncomingNack(*face1, nack1);
471 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 1);
472 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
473
474 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
475 strategyP->afterReceiveNack_count = 0;
476 strategyQ->afterReceiveNack_count = 0;
477 forwarder.onIncomingNack(*face1, nack2);
478 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
479 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 1);
480
481 // record Nack on PIT out-record
482 pit::OutRecordCollection::const_iterator outRecord1 = pit1->getOutRecord(*face1);
483 BOOST_REQUIRE(outRecord1 != pit1->getOutRecords().end());
484 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
485 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
486
487 // drop if no PIT entry
488 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
489 strategyP->afterReceiveNack_count = 0;
490 strategyQ->afterReceiveNack_count = 0;
491 forwarder.onIncomingNack(*face1, nack3);
492 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
493 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
494
495 // drop if no out-record
496 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
497 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
498 pit4->insertOrUpdateOutRecord(face1, *interest4);
499
500 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
501 strategyP->afterReceiveNack_count = 0;
502 strategyQ->afterReceiveNack_count = 0;
503 forwarder.onIncomingNack(*face2, nack4a);
504 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
505 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
506
507 // drop if Nonce does not match out-record
508 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
509 strategyP->afterReceiveNack_count = 0;
510 strategyQ->afterReceiveNack_count = 0;
511 forwarder.onIncomingNack(*face1, nack4b);
512 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
513 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
514
515 // drop if inFace is multi-access
516 pit4->insertOrUpdateOutRecord(face3, *interest4);
517 strategyP->afterReceiveNack_count = 0;
518 strategyQ->afterReceiveNack_count = 0;
519 forwarder.onIncomingNack(*face3, nack4a);
520 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
521 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
522}
523
524BOOST_AUTO_TEST_CASE(OutgoingNack)
525{
526 Forwarder forwarder;
527 auto face1w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>());
528 auto face1 = static_cast<DummyLpFace*>(face1w->getLpFace());
529 auto face2w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>());
530 auto face2 = static_cast<DummyLpFace*>(face2w->getLpFace());
531 auto face3w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>(
532 "dummy://", "dummy://",
533 ndn::nfd::FACE_SCOPE_NON_LOCAL,
534 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
535 ndn::nfd::LINK_TYPE_MULTI_ACCESS));
536 auto face3 = static_cast<DummyLpFace*>(face3w->getLpFace());
537 forwarder.addFace(face1w);
538 forwarder.addFace(face2w);
539 forwarder.addFace(face3w);
540 // TODO#3172 eliminate wrapper
541
542 Pit& pit = forwarder.getPit();
543
544 lp::NackHeader nackHeader;
545 nackHeader.setReason(lp::NackReason::CONGESTION);
546
547 // don't send Nack if there's no in-record
548 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
549 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
550 pit1->insertOrUpdateInRecord(face1w, *interest1);
551
552 face2->sentNacks.clear();
553 forwarder.onOutgoingNack(pit1, *face2w, nackHeader);
554 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
555
556 // send Nack with correct Nonce
557 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
558 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
559 pit2->insertOrUpdateInRecord(face1w, *interest2a);
560 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
561 pit2->insertOrUpdateInRecord(face2w, *interest2b);
562
563 face1->sentNacks.clear();
564 forwarder.onOutgoingNack(pit2, *face1w, nackHeader);
565 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
566 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
567 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
568
569 // erase in-record
570 pit::InRecordCollection::const_iterator inRecord2a = pit2->getInRecord(*face1w);
571 BOOST_CHECK(inRecord2a == pit2->getInRecords().end());
572
573 // send Nack with correct Nonce
574 face2->sentNacks.clear();
575 forwarder.onOutgoingNack(pit2, *face2w, nackHeader);
576 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
577 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
578 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
579
580 // erase in-record
581 pit::InRecordCollection::const_iterator inRecord2b = pit2->getInRecord(*face1w);
582 BOOST_CHECK(inRecord2b == pit2->getInRecords().end());
583
584 // don't send Nack to multi-access face
585 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
586 pit2->insertOrUpdateInRecord(face3w, *interest2c);
587
588 face3->sentNacks.clear();
589 forwarder.onOutgoingNack(pit1, *face3w, nackHeader);
590 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
591}
592
593BOOST_AUTO_TEST_CASE(InterestLoopNack)
594{
595 Forwarder forwarder;
596 auto face1w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>());
597 auto face1 = static_cast<DummyLpFace*>(face1w->getLpFace());
598 auto face2w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>());
599 auto face2 = static_cast<DummyLpFace*>(face2w->getLpFace());
600 auto face3w = make_shared<face::LpFaceWrapper>(make_unique<DummyLpFace>(
601 "dummy://", "dummy://",
602 ndn::nfd::FACE_SCOPE_NON_LOCAL,
603 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
604 ndn::nfd::LINK_TYPE_MULTI_ACCESS));
605 auto face3 = static_cast<DummyLpFace*>(face3w->getLpFace());
606 auto face4 = make_shared<DummyFace>();
607 forwarder.addFace(face1w);
608 forwarder.addFace(face2w);
609 forwarder.addFace(face3w);
610 forwarder.addFace(face4);
611 // TODO#3172 eliminate wrapper
612
613 Fib& fib = forwarder.getFib();
614 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("/zT4XwK0Hnx")).first;
615 fibEntry->addNextHop(face4, 0);
616
617 // receive Interest on face1
618 face1->sentNacks.clear();
619 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
620 face1->receiveInterest(*interest1a);
621 BOOST_CHECK(face1->sentNacks.empty());
622
623 // receive Interest with duplicate Nonce on face1
624 face1->sentNacks.clear();
625 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
626 face1->receiveInterest(*interest1b);
627 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
628 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
629 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
630
631 // receive Interest with duplicate Nonce on face2
632 face2->sentNacks.clear();
633 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
634 face2->receiveInterest(*interest2a);
635 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
636 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
637 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
638
639 // receive Interest with new Nonce on face2
640 face2->sentNacks.clear();
641 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
642 face2->receiveInterest(*interest2b);
643 BOOST_CHECK(face2->sentNacks.empty());
644
645 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
646 face3->sentNacks.clear();
647 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
648 face3->receiveInterest(*interest3a);
649 BOOST_CHECK(face3->sentNacks.empty());
650}
651
Junxiao Shi455581d2014-11-17 18:38:40 -0700652BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700653{
Junxiao Shia110f262014-10-12 12:35:20 -0700654 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700655 auto face1 = make_shared<DummyFace>();
656 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700657 forwarder.addFace(face1);
658 forwarder.addFace(face2);
659
660 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shic099ddb2014-12-25 20:53:20 -0700661 face2->onSendInterest.connect([&face1] (const Interest& interest) {
Junxiao Shi455581d2014-11-17 18:38:40 -0700662 scheduler::schedule(time::milliseconds(170), [&] { face1->receiveInterest(interest); });
Junxiao Shic099ddb2014-12-25 20:53:20 -0700663 });
Junxiao Shia110f262014-10-12 12:35:20 -0700664
665 Fib& fib = forwarder.getFib();
666 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
667 fibEntry->addNextHop(face2, 0);
668
Junxiao Shi455581d2014-11-17 18:38:40 -0700669 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700670 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
671 interest->setNonce(82101183);
672 interest->setInterestLifetime(time::milliseconds(50));
673 face1->receiveInterest(*interest);
674
Junxiao Shi455581d2014-11-17 18:38:40 -0700675 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
676 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
677 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700678
679 BOOST_CHECK_EQUAL(face2->m_sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700680
681 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
682 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
683 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
684 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
685 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700686}
687
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700688BOOST_AUTO_TEST_CASE(LinkDelegation)
689{
690 Forwarder forwarder;
691 shared_ptr<Face> face1 = make_shared<DummyFace>();
692 shared_ptr<Face> face2 = make_shared<DummyFace>();
693 forwarder.addFace(face1);
694 forwarder.addFace(face2);
695
696 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
697 auto strategyP = make_shared<DummyStrategy>(ref(forwarder), "ndn:/strategyP");
698 strategyP->wantAfterReceiveInterestCalls = true;
699 strategyChoice.install(strategyP);
700 strategyChoice.insert("ndn:/" , strategyP->getName());
701
702 Fib& fib = forwarder.getFib();
703 Pit& pit = forwarder.getPit();
704 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
705
706 // returns prefix of FIB entry during last afterReceiveInterest trigger
707 auto getLastFibPrefix = [strategyP] () -> Name {
708 BOOST_REQUIRE(!strategyP->afterReceiveInterestCalls.empty());
709 return std::get<2>(strategyP->afterReceiveInterestCalls.back())->getPrefix();
710 };
711
712 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
713
714 // consumer region
715 nrt.clear();
716 nrt.insert("/arizona/cs/avenir");
717 shared_ptr<fib::Entry> fibRoot = fib.insert("/").first;
718 fibRoot->addNextHop(face2, 10);
719
720 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
721 interest1->setLink(link->wireEncode());
722 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
723 pit1->insertOrUpdateInRecord(face1, *interest1);
724
725 forwarder.onContentStoreMiss(*face1, pit1, *interest1);
726 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/");
727 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
728
729 fibRoot->removeNextHop(face2);
730
731 // first default-free router, both delegations are available
732 nrt.clear();
733 nrt.insert("/arizona/cs/hobo");
734 shared_ptr<fib::Entry> fibTelia = fib.insert("/telia").first;
735 fibTelia->addNextHop(face2, 10);
736 shared_ptr<fib::Entry> fibUcla = fib.insert("/ucla").first;
737 fibUcla->addNextHop(face2, 10);
738
739 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
740 interest2->setLink(link->wireEncode());
741 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
742 pit2->insertOrUpdateInRecord(face1, *interest2);
743
744 forwarder.onContentStoreMiss(*face1, pit2, *interest2);
745 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/telia");
746 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
747 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
748
749 fib.erase(*fibTelia);
750 fib.erase(*fibUcla);
751
752 // first default-free router, only second delegation is available
753 nrt.clear();
754 nrt.insert("/arizona/cs/hobo");
755 fibUcla = fib.insert("/ucla").first;
756 fibUcla->addNextHop(face2, 10);
757
758 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
759 interest3->setLink(link->wireEncode());
760 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
761 pit3->insertOrUpdateInRecord(face1, *interest3);
762
763 forwarder.onContentStoreMiss(*face1, pit3, *interest3);
764 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
765 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
766 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
767
768 fib.erase(*fibUcla);
769
770 // default-free router, chosen SelectedDelegation
771 nrt.clear();
772 nrt.insert("/ucsd/caida/click");
773 fibTelia = fib.insert("/telia").first;
774 fibTelia->addNextHop(face2, 10);
775 fibUcla = fib.insert("/ucla").first;
776 fibUcla->addNextHop(face2, 10);
777
778 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
779 interest4->setLink(link->wireEncode());
780 interest4->setSelectedDelegation("/ucla/cs");
781 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
782 pit4->insertOrUpdateInRecord(face1, *interest4);
783
784 forwarder.onContentStoreMiss(*face1, pit4, *interest4);
785 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
786 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
787 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
788
789 fib.erase(*fibTelia);
790 fib.erase(*fibUcla);
791
792 // producer region
793 nrt.clear();
794 nrt.insert("/ucla/cs/spurs");
795 fibRoot->addNextHop(face2, 10);
796 fibUcla = fib.insert("/ucla").first;
797 fibUcla->addNextHop(face2, 10);
798 shared_ptr<fib::Entry> fibNdnsim = fib.insert("/net/ndnsim").first;
799 fibNdnsim->addNextHop(face2, 10);
800
801 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
802 interest5->setLink(link->wireEncode());
803 interest5->setSelectedDelegation("/ucla/cs");
804 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
805 pit5->insertOrUpdateInRecord(face1, *interest5);
806
807 forwarder.onContentStoreMiss(*face1, pit5, *interest5);
808 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/net/ndnsim");
809 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
810 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
811
812 fibRoot->removeNextHop(face2);
813 fib.erase(*fibUcla);
814 fib.erase(*fibNdnsim);
815}
816
817
818class MalformedPacketFixture : public UnitTestTimeFixture
819{
820protected:
821 MalformedPacketFixture()
822 : face1(make_shared<DummyFace>())
823 , face2(make_shared<DummyFace>())
824 {
825 forwarder.addFace(face1);
826 forwarder.addFace(face2);
827 }
828
829 void
830 processInterest(shared_ptr<Interest> badInterest)
831 {
832 forwarder.startProcessInterest(*face1, *badInterest);
833 this->continueProcessPacket();
834 }
835
836 // processData
837
838 // processNack
839
840private:
841 void
842 continueProcessPacket()
843 {
844 this->advanceClocks(time::milliseconds(10), time::seconds(6));
845 }
846
847protected:
848 Forwarder forwarder;
849 shared_ptr<DummyFace> face1; // face of incoming bad packet
850 shared_ptr<DummyFace> face2; // another face for setting up states
851};
852
853BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
854
855BOOST_AUTO_TEST_CASE(BadLink)
856{
857 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
858 Block wire = goodInterest->wireEncode();
859 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
860 wire.encode();
861
862 auto badInterest = make_shared<Interest>();
863 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
864 BOOST_REQUIRE(badInterest->hasLink());
865 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
866
867 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
868}
869
870BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
871
872BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700873BOOST_AUTO_TEST_SUITE_END()
874
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700875} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700876} // namespace nfd