blob: 906e2ca6efb655e53debd5e9872f9b1ef062a470 [file] [log] [blame]
Junxiao Shi8c8d2182014-01-30 22:33:00 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi330136a2016-03-10 04:53:08 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08004 * 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 Shif3c07812014-03-11 21:48:49 -070028#include "dummy-strategy.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070029
Junxiao Shid9ee45c2014-02-27 15:38:11 -070030#include "tests/test-common.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070031#include "tests/limited-io.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070032
33namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070034namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070035
Junxiao Shi0355e9f2015-09-02 07:24:53 -070036BOOST_AUTO_TEST_SUITE(Fw)
37BOOST_FIXTURE_TEST_SUITE(TestForwarder, BaseFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070038
Junxiao Shi8c8d2182014-01-30 22:33:00 -070039BOOST_AUTO_TEST_CASE(SimpleExchange)
40{
Junxiao Shi75ab6b72014-11-30 01:01:05 -070041 LimitedIo limitedIo;
42 auto afterOp = bind(&LimitedIo::afterOp, &limitedIo);;
Junxiao Shic041ca32014-02-25 20:01:15 -070043 Forwarder forwarder;
44
Junxiao Shi8c8d2182014-01-30 22:33:00 -070045 Name nameA ("ndn:/A");
46 Name nameAB ("ndn:/A/B");
47 Name nameABC("ndn:/A/B/C");
Junxiao Shif3c07812014-03-11 21:48:49 -070048 shared_ptr<Interest> interestAB = makeInterest(nameAB);
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070049 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shif3c07812014-03-11 21:48:49 -070050 shared_ptr<Data> dataABC = makeData(nameABC);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070051
Junxiao Shicde37ad2015-12-24 01:02:05 -070052 auto face1 = make_shared<DummyFace>();
53 auto face2 = make_shared<DummyFace>();
54 face1->afterSend.connect(bind(afterOp));
55 face2->afterSend.connect(bind(afterOp));
Junxiao Shi8c8d2182014-01-30 22:33:00 -070056 forwarder.addFace(face1);
57 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070058
Junxiao Shi8c8d2182014-01-30 22:33:00 -070059 Fib& fib = forwarder.getFib();
Junxiao Shi6e694322014-04-03 10:27:13 -070060 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
Junxiao Shi8c8d2182014-01-30 22:33:00 -070061 fibEntry->addNextHop(face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070062
Junxiao Shida93f1f2015-11-11 06:13:16 -070063 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
64 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070065 g_io.post([&] { face1->receiveInterest(*interestAB); });
66 BOOST_CHECK_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
Junxiao Shicde37ad2015-12-24 01:02:05 -070067 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
68 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), nameAB);
69 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
70 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070071 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
72 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070073
Junxiao Shida93f1f2015-11-11 06:13:16 -070074 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
75 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shi75ab6b72014-11-30 01:01:05 -070076 g_io.post([&] { face2->receiveData(*dataABC); });
77 BOOST_CHECK_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
Junxiao Shicde37ad2015-12-24 01:02:05 -070078 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
79 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), nameABC);
80 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
81 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070082 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
83 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070084}
85
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070086BOOST_AUTO_TEST_CASE(CsMatched)
87{
88 LimitedIo limitedIo;
89 Forwarder forwarder;
90
Junxiao Shicde37ad2015-12-24 01:02:05 -070091 auto face1 = make_shared<DummyFace>();
92 auto face2 = make_shared<DummyFace>();
93 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070094 forwarder.addFace(face1);
95 forwarder.addFace(face2);
96 forwarder.addFace(face3);
97
98 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
99 interestA->setInterestLifetime(time::seconds(4));
100 shared_ptr<Data> dataA = makeData("ndn:/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +0000101 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700102
103 Fib& fib = forwarder.getFib();
104 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
105 fibEntry->addNextHop(face2, 0);
106
107 Pit& pit = forwarder.getPit();
108 BOOST_CHECK_EQUAL(pit.size(), 0);
109
110 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700111 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700112
113 face1->receiveInterest(*interestA);
114 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
115 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700116 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700117
Junxiao Shicde37ad2015-12-24 01:02:05 -0700118 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700119 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700120 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
121 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700122
123 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(500));
124 // PIT entry should not be left behind
125 BOOST_CHECK_EQUAL(pit.size(), 0);
126}
127
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700128class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700129{
130public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700131 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700132 {
133 }
134
135 virtual void
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700136 onDataUnsolicited(Face& inFace, const Data& data) DECL_OVERRIDE
Junxiao Shi88884492014-02-15 15:57:43 -0700137 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700138 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700139 }
140
141protected:
142 virtual void
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700143 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) DECL_OVERRIDE
Junxiao Shi88884492014-02-15 15:57:43 -0700144 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700145 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700146 }
147
148public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700149 int dispatchToStrategy_count;
150 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700151};
152
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700153BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700154{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700155 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700156 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
157 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700158 forwarder.addFace(face1);
159 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700160
Junxiao Shi88884492014-02-15 15:57:43 -0700161 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700162 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700163 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800164 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700165 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700166
Junxiao Shi88884492014-02-15 15:57:43 -0700167 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700168 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700169 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800170 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700171 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700172
Junxiao Shi88884492014-02-15 15:57:43 -0700173 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700174 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700175 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800176 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700177 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700178
Junxiao Shi88884492014-02-15 15:57:43 -0700179 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700180 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700181 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800182 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700183 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700184
Junxiao Shi88884492014-02-15 15:57:43 -0700185 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700186 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700187 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800188 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700189 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700190
191 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700192 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700193 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800194 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700195 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700196
Junxiao Shi88884492014-02-15 15:57:43 -0700197 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700198 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700199 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800200 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700201 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700202
203 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700204 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700205 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800206 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700207 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700208}
209
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700210BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
211{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700212 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700213 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
214 auto face2 = make_shared<DummyFace>();
215 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700216 forwarder.addFace(face1);
217 forwarder.addFace(face2);
218 forwarder.addFace(face3);
219 Pit& pit = forwarder.getPit();
220
221 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700222 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
223 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
224 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700225 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700226 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700227 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700228
229 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700230 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
231 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
232 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700233 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700234 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700235 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700236
237 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700238 shared_ptr<Interest> interestA3 = makeInterest("/A3");
239 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
240 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700241 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700242 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700243 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700244
245 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700246 shared_ptr<Interest> interestA4 = makeInterest("/A4");
247 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
248 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700249 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700250 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700251 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700252
253 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700254 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700255 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700256 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700257
258 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700259 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700260 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700261 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700262
263 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700264 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700265 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700266 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700267
268 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700269 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700270 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700271 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700272}
273
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700274BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
275{
276 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700277 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
278 auto face2 = make_shared<DummyFace>();
279 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
280 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700281 forwarder.addFace(face1);
282 forwarder.addFace(face2);
283 forwarder.addFace(face3);
284 forwarder.addFace(face4);
285 Pit& pit = forwarder.getPit();
286
287 // from local face, to local face: OK
288 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
289 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
290 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700291 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700292 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700293 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700294
295 // from non-local face, to local face: OK
296 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
297 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
298 pit2->insertOrUpdateInRecord(face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700299 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700300 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700301 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700302
303 // from local face, to non-local face: OK
304 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
305 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
306 pit3->insertOrUpdateInRecord(face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700307 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700308 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700309 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700310
311 // from non-local face, to non-local face: violate
312 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
313 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
314 pit4->insertOrUpdateInRecord(face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700315 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700316 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700317 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700318
319 // from local face and non-local face, to local face: OK
320 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
321 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
322 pit5->insertOrUpdateInRecord(face1, *interest5);
323 pit5->insertOrUpdateInRecord(face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700324 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700325 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700326 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700327
328 // from local face and non-local face, to non-local face: OK
329 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
330 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
331 pit6->insertOrUpdateInRecord(face1, *interest6);
332 pit6->insertOrUpdateInRecord(face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700333 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700334 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700335 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700336}
337
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700338BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700339{
340 LimitedIo limitedIo;
341 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700342 auto face1 = make_shared<DummyFace>();
343 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700344 forwarder.addFace(face1);
345 forwarder.addFace(face2);
346
347 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
348 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700349 ref(forwarder), "ndn:/strategyP");
Junxiao Shif3c07812014-03-11 21:48:49 -0700350 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700351 ref(forwarder), "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700352 strategyChoice.install(strategyP);
353 strategyChoice.install(strategyQ);
354 strategyChoice.insert("ndn:/" , strategyP->getName());
355 strategyChoice.insert("ndn:/B", strategyQ->getName());
356
357 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700358 strategyP->afterReceiveInterest_count = 0;
359 strategyP->interestOutFace = face2;
360 forwarder.startProcessInterest(*face1, *interest1);
361 BOOST_CHECK_EQUAL(strategyP->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700362
363 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700364 strategyQ->afterReceiveInterest_count = 0;
365 strategyQ->interestOutFace = face2;
366 forwarder.startProcessInterest(*face1, *interest2);
367 BOOST_CHECK_EQUAL(strategyQ->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700368
369 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
370
371 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700372 strategyP->beforeSatisfyInterest_count = 0;
373 forwarder.startProcessData(*face2, *data1);
374 BOOST_CHECK_EQUAL(strategyP->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700375
376 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700377 strategyQ->beforeSatisfyInterest_count = 0;
378 forwarder.startProcessData(*face2, *data2);
379 BOOST_CHECK_EQUAL(strategyQ->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700380
381 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700382 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700383 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700384 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700385 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700386 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700387
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700388 strategyP->beforeExpirePendingInterest_count = 0;
389 strategyQ->beforeExpirePendingInterest_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700390 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(100));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700391 BOOST_CHECK_EQUAL(strategyP->beforeExpirePendingInterest_count, 1);
392 BOOST_CHECK_EQUAL(strategyQ->beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700393}
394
Junxiao Shida006f52014-05-16 11:18:00 -0700395BOOST_AUTO_TEST_CASE(IncomingData)
396{
397 LimitedIo limitedIo;
398 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700399 auto face1 = make_shared<DummyFace>();
400 auto face2 = make_shared<DummyFace>();
401 auto face3 = make_shared<DummyFace>();
402 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700403 forwarder.addFace(face1);
404 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700405 forwarder.addFace(face3);
406 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700407
408 Pit& pit = forwarder.getPit();
409 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
410 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
411 pit0->insertOrUpdateInRecord(face1, *interest0);
412 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
413 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
414 pitA->insertOrUpdateInRecord(face1, *interestA);
415 pitA->insertOrUpdateInRecord(face2, *interestA);
416 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
417 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
418 pitC->insertOrUpdateInRecord(face3, *interestC);
419 pitC->insertOrUpdateInRecord(face4, *interestC);
420
421 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
422 forwarder.onIncomingData(*face3, *dataD);
423 limitedIo.run(LimitedIo::UNLIMITED_OPS, time::milliseconds(5));
424
Junxiao Shicde37ad2015-12-24 01:02:05 -0700425 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
426 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
427 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
428 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700429}
430
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700431BOOST_AUTO_TEST_CASE(IncomingNack)
432{
433 Forwarder forwarder;
434 auto face1 = make_shared<DummyFace>();
435 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700436 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
437 ndn::nfd::FACE_SCOPE_NON_LOCAL,
438 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
439 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700440 forwarder.addFace(face1);
441 forwarder.addFace(face2);
442 forwarder.addFace(face3);
443
444 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
445 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
446 ref(forwarder), "ndn:/strategyP");
447 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
448 ref(forwarder), "ndn:/strategyQ");
449 strategyChoice.install(strategyP);
450 strategyChoice.install(strategyQ);
451 strategyChoice.insert("ndn:/" , strategyP->getName());
452 strategyChoice.insert("ndn:/B", strategyQ->getName());
453
454 Pit& pit = forwarder.getPit();
455
456 // dispatch to the correct strategy
457 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
458 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
459 pit1->insertOrUpdateOutRecord(face1, *interest1);
460 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
461 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
462 pit2->insertOrUpdateOutRecord(face1, *interest2);
463
464 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
465 strategyP->afterReceiveNack_count = 0;
466 strategyQ->afterReceiveNack_count = 0;
467 forwarder.onIncomingNack(*face1, nack1);
468 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 1);
469 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
470
471 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
472 strategyP->afterReceiveNack_count = 0;
473 strategyQ->afterReceiveNack_count = 0;
474 forwarder.onIncomingNack(*face1, nack2);
475 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
476 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 1);
477
478 // record Nack on PIT out-record
479 pit::OutRecordCollection::const_iterator outRecord1 = pit1->getOutRecord(*face1);
480 BOOST_REQUIRE(outRecord1 != pit1->getOutRecords().end());
481 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
482 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
483
484 // drop if no PIT entry
485 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
486 strategyP->afterReceiveNack_count = 0;
487 strategyQ->afterReceiveNack_count = 0;
488 forwarder.onIncomingNack(*face1, nack3);
489 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
490 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
491
492 // drop if no out-record
493 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
494 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
495 pit4->insertOrUpdateOutRecord(face1, *interest4);
496
497 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
498 strategyP->afterReceiveNack_count = 0;
499 strategyQ->afterReceiveNack_count = 0;
500 forwarder.onIncomingNack(*face2, nack4a);
501 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
502 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
503
504 // drop if Nonce does not match out-record
505 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
506 strategyP->afterReceiveNack_count = 0;
507 strategyQ->afterReceiveNack_count = 0;
508 forwarder.onIncomingNack(*face1, nack4b);
509 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
510 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
511
512 // drop if inFace is multi-access
513 pit4->insertOrUpdateOutRecord(face3, *interest4);
514 strategyP->afterReceiveNack_count = 0;
515 strategyQ->afterReceiveNack_count = 0;
516 forwarder.onIncomingNack(*face3, nack4a);
517 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
518 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
519}
520
521BOOST_AUTO_TEST_CASE(OutgoingNack)
522{
523 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700524 auto face1 = make_shared<DummyFace>();
525 auto face2 = make_shared<DummyFace>();
526 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
527 ndn::nfd::FACE_SCOPE_NON_LOCAL,
528 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
529 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
530 forwarder.addFace(face1);
531 forwarder.addFace(face2);
532 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700533
534 Pit& pit = forwarder.getPit();
535
536 lp::NackHeader nackHeader;
537 nackHeader.setReason(lp::NackReason::CONGESTION);
538
539 // don't send Nack if there's no in-record
540 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
541 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700542 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700543
544 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700545 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700546 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
547
548 // send Nack with correct Nonce
549 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
550 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700551 pit2->insertOrUpdateInRecord(face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700552 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700553 pit2->insertOrUpdateInRecord(face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700554
555 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700556 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700557 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
558 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
559 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
560
561 // erase in-record
Junxiao Shicde37ad2015-12-24 01:02:05 -0700562 pit::InRecordCollection::const_iterator inRecord2a = pit2->getInRecord(*face1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700563 BOOST_CHECK(inRecord2a == pit2->getInRecords().end());
564
565 // send Nack with correct Nonce
566 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700567 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700568 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
569 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
570 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
571
572 // erase in-record
Junxiao Shicde37ad2015-12-24 01:02:05 -0700573 pit::InRecordCollection::const_iterator inRecord2b = pit2->getInRecord(*face1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700574 BOOST_CHECK(inRecord2b == pit2->getInRecords().end());
575
576 // don't send Nack to multi-access face
577 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700578 pit2->insertOrUpdateInRecord(face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700579
580 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700581 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700582 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
583}
584
585BOOST_AUTO_TEST_CASE(InterestLoopNack)
586{
587 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700588 auto face1 = make_shared<DummyFace>();
589 auto face2 = make_shared<DummyFace>();
590 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
591 ndn::nfd::FACE_SCOPE_NON_LOCAL,
592 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
593 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700594 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700595 forwarder.addFace(face1);
596 forwarder.addFace(face2);
597 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700598 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700599
600 Fib& fib = forwarder.getFib();
601 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("/zT4XwK0Hnx")).first;
602 fibEntry->addNextHop(face4, 0);
603
604 // receive Interest on face1
605 face1->sentNacks.clear();
606 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
607 face1->receiveInterest(*interest1a);
608 BOOST_CHECK(face1->sentNacks.empty());
609
610 // receive Interest with duplicate Nonce on face1
611 face1->sentNacks.clear();
612 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
613 face1->receiveInterest(*interest1b);
614 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
615 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
616 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
617
618 // receive Interest with duplicate Nonce on face2
619 face2->sentNacks.clear();
620 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
621 face2->receiveInterest(*interest2a);
622 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
623 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
624 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
625
626 // receive Interest with new Nonce on face2
627 face2->sentNacks.clear();
628 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
629 face2->receiveInterest(*interest2b);
630 BOOST_CHECK(face2->sentNacks.empty());
631
632 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
633 face3->sentNacks.clear();
634 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
635 face3->receiveInterest(*interest3a);
636 BOOST_CHECK(face3->sentNacks.empty());
637}
638
Junxiao Shi455581d2014-11-17 18:38:40 -0700639BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700640{
Junxiao Shia110f262014-10-12 12:35:20 -0700641 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700642 auto face1 = make_shared<DummyFace>();
643 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700644 forwarder.addFace(face1);
645 forwarder.addFace(face2);
646
647 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700648 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
649 if (pktType == tlv::Interest) {
650 auto interest = make_shared<Interest>(face2->sentInterests.back());
651 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
652 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700653 });
Junxiao Shia110f262014-10-12 12:35:20 -0700654
655 Fib& fib = forwarder.getFib();
656 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
657 fibEntry->addNextHop(face2, 0);
658
Junxiao Shi455581d2014-11-17 18:38:40 -0700659 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700660 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
661 interest->setNonce(82101183);
662 interest->setInterestLifetime(time::milliseconds(50));
663 face1->receiveInterest(*interest);
664
Junxiao Shi455581d2014-11-17 18:38:40 -0700665 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
666 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
667 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700668
Junxiao Shicde37ad2015-12-24 01:02:05 -0700669 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700670
671 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
672 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
673 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
674 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
675 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700676}
677
Junxiao Shi330136a2016-03-10 04:53:08 -0700678BOOST_FIXTURE_TEST_CASE(PitLeak, UnitTestTimeFixture) // Bug 3484
679{
680 Forwarder forwarder;
681 shared_ptr<Face> face1 = make_shared<DummyFace>();
682 forwarder.addFace(face1);
683
684 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
685 interest->setNonce(61883075);
686 interest->setInterestLifetime(time::seconds(2));
687
688 DeadNonceList& dnl = forwarder.getDeadNonceList();
689 dnl.add(interest->getName(), interest->getNonce());
690 Pit& pit = forwarder.getPit();
691 BOOST_REQUIRE_EQUAL(pit.size(), 0);
692
693 forwarder.startProcessInterest(*face1, *interest);
694 this->advanceClocks(time::milliseconds(100), time::seconds(20));
695 BOOST_CHECK_EQUAL(pit.size(), 0);
696}
697
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700698BOOST_AUTO_TEST_CASE(LinkDelegation)
699{
700 Forwarder forwarder;
701 shared_ptr<Face> face1 = make_shared<DummyFace>();
702 shared_ptr<Face> face2 = make_shared<DummyFace>();
703 forwarder.addFace(face1);
704 forwarder.addFace(face2);
705
706 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
707 auto strategyP = make_shared<DummyStrategy>(ref(forwarder), "ndn:/strategyP");
708 strategyP->wantAfterReceiveInterestCalls = true;
709 strategyChoice.install(strategyP);
710 strategyChoice.insert("ndn:/" , strategyP->getName());
711
712 Fib& fib = forwarder.getFib();
713 Pit& pit = forwarder.getPit();
714 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
715
716 // returns prefix of FIB entry during last afterReceiveInterest trigger
717 auto getLastFibPrefix = [strategyP] () -> Name {
718 BOOST_REQUIRE(!strategyP->afterReceiveInterestCalls.empty());
719 return std::get<2>(strategyP->afterReceiveInterestCalls.back())->getPrefix();
720 };
721
722 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
723
724 // consumer region
725 nrt.clear();
726 nrt.insert("/arizona/cs/avenir");
727 shared_ptr<fib::Entry> fibRoot = fib.insert("/").first;
728 fibRoot->addNextHop(face2, 10);
729
730 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
731 interest1->setLink(link->wireEncode());
732 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
733 pit1->insertOrUpdateInRecord(face1, *interest1);
734
735 forwarder.onContentStoreMiss(*face1, pit1, *interest1);
736 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/");
737 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
738
739 fibRoot->removeNextHop(face2);
740
741 // first default-free router, both delegations are available
742 nrt.clear();
743 nrt.insert("/arizona/cs/hobo");
744 shared_ptr<fib::Entry> fibTelia = fib.insert("/telia").first;
745 fibTelia->addNextHop(face2, 10);
746 shared_ptr<fib::Entry> fibUcla = fib.insert("/ucla").first;
747 fibUcla->addNextHop(face2, 10);
748
749 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
750 interest2->setLink(link->wireEncode());
751 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
752 pit2->insertOrUpdateInRecord(face1, *interest2);
753
754 forwarder.onContentStoreMiss(*face1, pit2, *interest2);
755 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/telia");
756 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
757 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
758
759 fib.erase(*fibTelia);
760 fib.erase(*fibUcla);
761
762 // first default-free router, only second delegation is available
763 nrt.clear();
764 nrt.insert("/arizona/cs/hobo");
765 fibUcla = fib.insert("/ucla").first;
766 fibUcla->addNextHop(face2, 10);
767
768 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
769 interest3->setLink(link->wireEncode());
770 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
771 pit3->insertOrUpdateInRecord(face1, *interest3);
772
773 forwarder.onContentStoreMiss(*face1, pit3, *interest3);
774 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
775 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
776 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
777
778 fib.erase(*fibUcla);
779
780 // default-free router, chosen SelectedDelegation
781 nrt.clear();
782 nrt.insert("/ucsd/caida/click");
783 fibTelia = fib.insert("/telia").first;
784 fibTelia->addNextHop(face2, 10);
785 fibUcla = fib.insert("/ucla").first;
786 fibUcla->addNextHop(face2, 10);
787
788 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
789 interest4->setLink(link->wireEncode());
790 interest4->setSelectedDelegation("/ucla/cs");
791 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
792 pit4->insertOrUpdateInRecord(face1, *interest4);
793
794 forwarder.onContentStoreMiss(*face1, pit4, *interest4);
795 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
796 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
797 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
798
799 fib.erase(*fibTelia);
800 fib.erase(*fibUcla);
801
802 // producer region
803 nrt.clear();
804 nrt.insert("/ucla/cs/spurs");
805 fibRoot->addNextHop(face2, 10);
806 fibUcla = fib.insert("/ucla").first;
807 fibUcla->addNextHop(face2, 10);
808 shared_ptr<fib::Entry> fibNdnsim = fib.insert("/net/ndnsim").first;
809 fibNdnsim->addNextHop(face2, 10);
810
811 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
812 interest5->setLink(link->wireEncode());
813 interest5->setSelectedDelegation("/ucla/cs");
814 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
815 pit5->insertOrUpdateInRecord(face1, *interest5);
816
817 forwarder.onContentStoreMiss(*face1, pit5, *interest5);
818 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/net/ndnsim");
819 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
820 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
821
822 fibRoot->removeNextHop(face2);
823 fib.erase(*fibUcla);
824 fib.erase(*fibNdnsim);
825}
826
827
828class MalformedPacketFixture : public UnitTestTimeFixture
829{
830protected:
831 MalformedPacketFixture()
832 : face1(make_shared<DummyFace>())
833 , face2(make_shared<DummyFace>())
834 {
835 forwarder.addFace(face1);
836 forwarder.addFace(face2);
837 }
838
839 void
840 processInterest(shared_ptr<Interest> badInterest)
841 {
842 forwarder.startProcessInterest(*face1, *badInterest);
843 this->continueProcessPacket();
844 }
845
846 // processData
847
848 // processNack
849
850private:
851 void
852 continueProcessPacket()
853 {
854 this->advanceClocks(time::milliseconds(10), time::seconds(6));
855 }
856
857protected:
858 Forwarder forwarder;
859 shared_ptr<DummyFace> face1; // face of incoming bad packet
860 shared_ptr<DummyFace> face2; // another face for setting up states
861};
862
863BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
864
865BOOST_AUTO_TEST_CASE(BadLink)
866{
867 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
868 Block wire = goodInterest->wireEncode();
869 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
870 wire.encode();
871
872 auto badInterest = make_shared<Interest>();
873 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
874 BOOST_REQUIRE(badInterest->hasLink());
875 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
876
877 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
878}
879
880BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
881
882BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700883BOOST_AUTO_TEST_SUITE_END()
884
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700885} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700886} // namespace nfd