blob: 6bbad7796b80c6bea551fdf56e35a5b1f1c1fd73 [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"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070031
32namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070033namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070034
Junxiao Shi0355e9f2015-09-02 07:24:53 -070035BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shid41d6072016-06-19 23:35:27 +000036BOOST_FIXTURE_TEST_SUITE(TestForwarder, UnitTestTimeFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070037
Junxiao Shi8c8d2182014-01-30 22:33:00 -070038BOOST_AUTO_TEST_CASE(SimpleExchange)
39{
Junxiao Shic041ca32014-02-25 20:01:15 -070040 Forwarder forwarder;
41
Junxiao Shid41d6072016-06-19 23:35:27 +000042 Name nameA("ndn:/A");
43 Name nameAB("ndn:/A/B");
Junxiao Shi8c8d2182014-01-30 22:33:00 -070044 Name nameABC("ndn:/A/B/C");
Junxiao Shif3c07812014-03-11 21:48:49 -070045 shared_ptr<Interest> interestAB = makeInterest(nameAB);
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070046 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shif3c07812014-03-11 21:48:49 -070047 shared_ptr<Data> dataABC = makeData(nameABC);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070048
Junxiao Shicde37ad2015-12-24 01:02:05 -070049 auto face1 = make_shared<DummyFace>();
50 auto face2 = make_shared<DummyFace>();
Junxiao Shi8c8d2182014-01-30 22:33:00 -070051 forwarder.addFace(face1);
52 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070053
Junxiao Shi8c8d2182014-01-30 22:33:00 -070054 Fib& fib = forwarder.getFib();
Junxiao Shi6e694322014-04-03 10:27:13 -070055 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
Junxiao Shi8c8d2182014-01-30 22:33:00 -070056 fibEntry->addNextHop(face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070057
Junxiao Shida93f1f2015-11-11 06:13:16 -070058 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
59 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000060 face1->receiveInterest(*interestAB);
61 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070062 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
63 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), nameAB);
64 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
65 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070066 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
67 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070068
Junxiao Shida93f1f2015-11-11 06:13:16 -070069 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
70 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000071 face2->receiveData(*dataABC);
72 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070073 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
74 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), nameABC);
75 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
76 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070077 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
78 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070079}
80
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070081BOOST_AUTO_TEST_CASE(CsMatched)
82{
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070083 Forwarder forwarder;
84
Junxiao Shicde37ad2015-12-24 01:02:05 -070085 auto face1 = make_shared<DummyFace>();
86 auto face2 = make_shared<DummyFace>();
87 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070088 forwarder.addFace(face1);
89 forwarder.addFace(face2);
90 forwarder.addFace(face3);
91
92 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
93 interestA->setInterestLifetime(time::seconds(4));
94 shared_ptr<Data> dataA = makeData("ndn:/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +000095 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070096
97 Fib& fib = forwarder.getFib();
98 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
99 fibEntry->addNextHop(face2, 0);
100
101 Pit& pit = forwarder.getPit();
102 BOOST_CHECK_EQUAL(pit.size(), 0);
103
104 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700105 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700106
107 face1->receiveInterest(*interestA);
Junxiao Shid41d6072016-06-19 23:35:27 +0000108 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700109 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700110 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700111
Junxiao Shicde37ad2015-12-24 01:02:05 -0700112 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700113 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700114 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
115 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700116
Junxiao Shid41d6072016-06-19 23:35:27 +0000117 this->advanceClocks(time::milliseconds(100), time::milliseconds(500));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700118 // PIT entry should not be left behind
119 BOOST_CHECK_EQUAL(pit.size(), 0);
120}
121
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700122class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700123{
124public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700125 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700126 {
127 }
128
129 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200130 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700131 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700132 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700133 }
134
135protected:
136 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200137 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) override
Junxiao Shi88884492014-02-15 15:57:43 -0700138 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700139 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700140 }
141
142public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700143 int dispatchToStrategy_count;
144 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700145};
146
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700147BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700148{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700149 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700150 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
151 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700152 forwarder.addFace(face1);
153 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700154
Junxiao Shi88884492014-02-15 15:57:43 -0700155 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700156 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700157 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800158 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700159 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700160
Junxiao Shi88884492014-02-15 15:57:43 -0700161 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700162 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700163 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800164 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700165 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700166
Junxiao Shi88884492014-02-15 15:57:43 -0700167 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700168 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700169 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800170 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700171 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700172
Junxiao Shi88884492014-02-15 15:57:43 -0700173 // non-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> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800176 forwarder.onIncomingInterest(*face2, *i4);
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 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700180 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700181 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800182 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700183 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700184
185 // non-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> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800188 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700189 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700190
Junxiao Shi88884492014-02-15 15:57:43 -0700191 // local face, non-/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> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800194 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700195 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700196
197 // non-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> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800200 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700201 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700202}
203
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700204BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
205{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700206 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700207 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
208 auto face2 = make_shared<DummyFace>();
209 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700210 forwarder.addFace(face1);
211 forwarder.addFace(face2);
212 forwarder.addFace(face3);
213 Pit& pit = forwarder.getPit();
214
215 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700216 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
217 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
218 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700219 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700220 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700221 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700222
223 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700224 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
225 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
226 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700227 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700228 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700229 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700230
231 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700232 shared_ptr<Interest> interestA3 = makeInterest("/A3");
233 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
234 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700235 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700236 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700237 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700238
239 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700240 shared_ptr<Interest> interestA4 = makeInterest("/A4");
241 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
242 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700243 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700244 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700245 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700246
247 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700248 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700249 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700250 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700251
252 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700253 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700254 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700255 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700256
257 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700258 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700259 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700260 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700261
262 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700263 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700264 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700265 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700266}
267
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700268BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
269{
270 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700271 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
272 auto face2 = make_shared<DummyFace>();
273 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
274 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700275 forwarder.addFace(face1);
276 forwarder.addFace(face2);
277 forwarder.addFace(face3);
278 forwarder.addFace(face4);
279 Pit& pit = forwarder.getPit();
280
281 // from local face, to local face: OK
282 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
283 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
284 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700285 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700286 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700287 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700288
289 // from non-local face, to local face: OK
290 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
291 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
292 pit2->insertOrUpdateInRecord(face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700293 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700294 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700295 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700296
297 // from local face, to non-local face: OK
298 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
299 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
300 pit3->insertOrUpdateInRecord(face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700301 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700302 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700303 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700304
305 // from non-local face, to non-local face: violate
306 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
307 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
308 pit4->insertOrUpdateInRecord(face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700309 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700310 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700311 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700312
313 // from local face and non-local face, to local face: OK
314 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
315 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
316 pit5->insertOrUpdateInRecord(face1, *interest5);
317 pit5->insertOrUpdateInRecord(face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700318 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700319 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700320 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700321
322 // from local face and non-local face, to non-local face: OK
323 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
324 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
325 pit6->insertOrUpdateInRecord(face1, *interest6);
326 pit6->insertOrUpdateInRecord(face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700327 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700328 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700329 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700330}
331
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700332BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700333{
Junxiao Shif3c07812014-03-11 21:48:49 -0700334 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700335 auto face1 = make_shared<DummyFace>();
336 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700337 forwarder.addFace(face1);
338 forwarder.addFace(face2);
339
340 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
341 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700342 ref(forwarder), "ndn:/strategyP");
Junxiao Shif3c07812014-03-11 21:48:49 -0700343 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700344 ref(forwarder), "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700345 strategyChoice.install(strategyP);
346 strategyChoice.install(strategyQ);
347 strategyChoice.insert("ndn:/" , strategyP->getName());
348 strategyChoice.insert("ndn:/B", strategyQ->getName());
349
350 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700351 strategyP->afterReceiveInterest_count = 0;
352 strategyP->interestOutFace = face2;
353 forwarder.startProcessInterest(*face1, *interest1);
354 BOOST_CHECK_EQUAL(strategyP->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700355
356 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700357 strategyQ->afterReceiveInterest_count = 0;
358 strategyQ->interestOutFace = face2;
359 forwarder.startProcessInterest(*face1, *interest2);
360 BOOST_CHECK_EQUAL(strategyQ->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700361
Junxiao Shid41d6072016-06-19 23:35:27 +0000362 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700363
364 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700365 strategyP->beforeSatisfyInterest_count = 0;
366 forwarder.startProcessData(*face2, *data1);
367 BOOST_CHECK_EQUAL(strategyP->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700368
369 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700370 strategyQ->beforeSatisfyInterest_count = 0;
371 forwarder.startProcessData(*face2, *data2);
372 BOOST_CHECK_EQUAL(strategyQ->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700373
374 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700375 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700376 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700377 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700378 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700379 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700380
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700381 strategyP->beforeExpirePendingInterest_count = 0;
382 strategyQ->beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000383 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700384 BOOST_CHECK_EQUAL(strategyP->beforeExpirePendingInterest_count, 1);
385 BOOST_CHECK_EQUAL(strategyQ->beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700386}
387
Junxiao Shida006f52014-05-16 11:18:00 -0700388BOOST_AUTO_TEST_CASE(IncomingData)
389{
Junxiao Shida006f52014-05-16 11:18:00 -0700390 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700391 auto face1 = make_shared<DummyFace>();
392 auto face2 = make_shared<DummyFace>();
393 auto face3 = make_shared<DummyFace>();
394 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700395 forwarder.addFace(face1);
396 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700397 forwarder.addFace(face3);
398 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700399
400 Pit& pit = forwarder.getPit();
401 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
402 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
403 pit0->insertOrUpdateInRecord(face1, *interest0);
404 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
405 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
406 pitA->insertOrUpdateInRecord(face1, *interestA);
407 pitA->insertOrUpdateInRecord(face2, *interestA);
408 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
409 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
410 pitC->insertOrUpdateInRecord(face3, *interestC);
411 pitC->insertOrUpdateInRecord(face4, *interestC);
412
413 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
414 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000415 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700416
Junxiao Shicde37ad2015-12-24 01:02:05 -0700417 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
418 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
419 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
420 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700421}
422
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700423BOOST_AUTO_TEST_CASE(IncomingNack)
424{
425 Forwarder forwarder;
426 auto face1 = make_shared<DummyFace>();
427 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700428 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
429 ndn::nfd::FACE_SCOPE_NON_LOCAL,
430 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
431 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700432 forwarder.addFace(face1);
433 forwarder.addFace(face2);
434 forwarder.addFace(face3);
435
436 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
437 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
438 ref(forwarder), "ndn:/strategyP");
439 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
440 ref(forwarder), "ndn:/strategyQ");
441 strategyChoice.install(strategyP);
442 strategyChoice.install(strategyQ);
443 strategyChoice.insert("ndn:/" , strategyP->getName());
444 strategyChoice.insert("ndn:/B", strategyQ->getName());
445
446 Pit& pit = forwarder.getPit();
447
448 // dispatch to the correct strategy
449 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
450 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
451 pit1->insertOrUpdateOutRecord(face1, *interest1);
452 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
453 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
454 pit2->insertOrUpdateOutRecord(face1, *interest2);
455
456 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
457 strategyP->afterReceiveNack_count = 0;
458 strategyQ->afterReceiveNack_count = 0;
459 forwarder.onIncomingNack(*face1, nack1);
460 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 1);
461 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
462
463 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
464 strategyP->afterReceiveNack_count = 0;
465 strategyQ->afterReceiveNack_count = 0;
466 forwarder.onIncomingNack(*face1, nack2);
467 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
468 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 1);
469
470 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700471 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
472 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700473 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
474 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
475
476 // drop if no PIT entry
477 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
478 strategyP->afterReceiveNack_count = 0;
479 strategyQ->afterReceiveNack_count = 0;
480 forwarder.onIncomingNack(*face1, nack3);
481 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
482 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
483
484 // drop if no out-record
485 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
486 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
487 pit4->insertOrUpdateOutRecord(face1, *interest4);
488
489 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
490 strategyP->afterReceiveNack_count = 0;
491 strategyQ->afterReceiveNack_count = 0;
492 forwarder.onIncomingNack(*face2, nack4a);
493 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
494 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
495
496 // drop if Nonce does not match out-record
497 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
498 strategyP->afterReceiveNack_count = 0;
499 strategyQ->afterReceiveNack_count = 0;
500 forwarder.onIncomingNack(*face1, nack4b);
501 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
502 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
503
504 // drop if inFace is multi-access
505 pit4->insertOrUpdateOutRecord(face3, *interest4);
506 strategyP->afterReceiveNack_count = 0;
507 strategyQ->afterReceiveNack_count = 0;
508 forwarder.onIncomingNack(*face3, nack4a);
509 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
510 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
511}
512
513BOOST_AUTO_TEST_CASE(OutgoingNack)
514{
515 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700516 auto face1 = make_shared<DummyFace>();
517 auto face2 = make_shared<DummyFace>();
518 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
519 ndn::nfd::FACE_SCOPE_NON_LOCAL,
520 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
521 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
522 forwarder.addFace(face1);
523 forwarder.addFace(face2);
524 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700525
526 Pit& pit = forwarder.getPit();
527
528 lp::NackHeader nackHeader;
529 nackHeader.setReason(lp::NackReason::CONGESTION);
530
531 // don't send Nack if there's no in-record
532 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
533 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700534 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700535
536 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700537 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700538 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
539
540 // send Nack with correct Nonce
541 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
542 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700543 pit2->insertOrUpdateInRecord(face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700544 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700545 pit2->insertOrUpdateInRecord(face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700546
547 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700548 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700549 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
550 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
551 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
552
553 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700554 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
555 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700556
557 // send Nack with correct Nonce
558 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700559 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700560 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
561 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
562 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
563
564 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700565 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
566 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700567
568 // don't send Nack to multi-access face
569 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700570 pit2->insertOrUpdateInRecord(face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700571
572 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700573 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700574 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
575}
576
577BOOST_AUTO_TEST_CASE(InterestLoopNack)
578{
579 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700580 auto face1 = make_shared<DummyFace>();
581 auto face2 = make_shared<DummyFace>();
582 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
583 ndn::nfd::FACE_SCOPE_NON_LOCAL,
584 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
585 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700586 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700587 forwarder.addFace(face1);
588 forwarder.addFace(face2);
589 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700590 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700591
592 Fib& fib = forwarder.getFib();
593 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("/zT4XwK0Hnx")).first;
594 fibEntry->addNextHop(face4, 0);
595
596 // receive Interest on face1
597 face1->sentNacks.clear();
598 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
599 face1->receiveInterest(*interest1a);
600 BOOST_CHECK(face1->sentNacks.empty());
601
602 // receive Interest with duplicate Nonce on face1
603 face1->sentNacks.clear();
604 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
605 face1->receiveInterest(*interest1b);
606 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
607 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
608 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
609
610 // receive Interest with duplicate Nonce on face2
611 face2->sentNacks.clear();
612 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
613 face2->receiveInterest(*interest2a);
614 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
615 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
616 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
617
618 // receive Interest with new Nonce on face2
619 face2->sentNacks.clear();
620 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
621 face2->receiveInterest(*interest2b);
622 BOOST_CHECK(face2->sentNacks.empty());
623
624 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
625 face3->sentNacks.clear();
626 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
627 face3->receiveInterest(*interest3a);
628 BOOST_CHECK(face3->sentNacks.empty());
629}
630
Junxiao Shi455581d2014-11-17 18:38:40 -0700631BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700632{
Junxiao Shia110f262014-10-12 12:35:20 -0700633 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700634 auto face1 = make_shared<DummyFace>();
635 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700636 forwarder.addFace(face1);
637 forwarder.addFace(face2);
638
639 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700640 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
641 if (pktType == tlv::Interest) {
642 auto interest = make_shared<Interest>(face2->sentInterests.back());
643 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
644 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700645 });
Junxiao Shia110f262014-10-12 12:35:20 -0700646
647 Fib& fib = forwarder.getFib();
648 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
649 fibEntry->addNextHop(face2, 0);
650
Junxiao Shi455581d2014-11-17 18:38:40 -0700651 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700652 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
653 interest->setNonce(82101183);
654 interest->setInterestLifetime(time::milliseconds(50));
655 face1->receiveInterest(*interest);
656
Junxiao Shi455581d2014-11-17 18:38:40 -0700657 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
658 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
659 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700660
Junxiao Shicde37ad2015-12-24 01:02:05 -0700661 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700662
663 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
664 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
665 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
666 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
667 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700668}
669
Junxiao Shid41d6072016-06-19 23:35:27 +0000670BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700671{
672 Forwarder forwarder;
673 shared_ptr<Face> face1 = make_shared<DummyFace>();
674 forwarder.addFace(face1);
675
676 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
677 interest->setNonce(61883075);
678 interest->setInterestLifetime(time::seconds(2));
679
680 DeadNonceList& dnl = forwarder.getDeadNonceList();
681 dnl.add(interest->getName(), interest->getNonce());
682 Pit& pit = forwarder.getPit();
683 BOOST_REQUIRE_EQUAL(pit.size(), 0);
684
685 forwarder.startProcessInterest(*face1, *interest);
686 this->advanceClocks(time::milliseconds(100), time::seconds(20));
687 BOOST_CHECK_EQUAL(pit.size(), 0);
688}
689
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700690BOOST_AUTO_TEST_CASE(LinkDelegation)
691{
692 Forwarder forwarder;
693 shared_ptr<Face> face1 = make_shared<DummyFace>();
694 shared_ptr<Face> face2 = make_shared<DummyFace>();
695 forwarder.addFace(face1);
696 forwarder.addFace(face2);
697
698 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
699 auto strategyP = make_shared<DummyStrategy>(ref(forwarder), "ndn:/strategyP");
700 strategyP->wantAfterReceiveInterestCalls = true;
701 strategyChoice.install(strategyP);
702 strategyChoice.insert("ndn:/" , strategyP->getName());
703
704 Fib& fib = forwarder.getFib();
705 Pit& pit = forwarder.getPit();
706 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
707
708 // returns prefix of FIB entry during last afterReceiveInterest trigger
709 auto getLastFibPrefix = [strategyP] () -> Name {
710 BOOST_REQUIRE(!strategyP->afterReceiveInterestCalls.empty());
711 return std::get<2>(strategyP->afterReceiveInterestCalls.back())->getPrefix();
712 };
713
714 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
715
716 // consumer region
717 nrt.clear();
718 nrt.insert("/arizona/cs/avenir");
719 shared_ptr<fib::Entry> fibRoot = fib.insert("/").first;
720 fibRoot->addNextHop(face2, 10);
721
722 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
723 interest1->setLink(link->wireEncode());
724 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
725 pit1->insertOrUpdateInRecord(face1, *interest1);
726
727 forwarder.onContentStoreMiss(*face1, pit1, *interest1);
728 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/");
729 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
730
731 fibRoot->removeNextHop(face2);
732
733 // first default-free router, both delegations are available
734 nrt.clear();
735 nrt.insert("/arizona/cs/hobo");
736 shared_ptr<fib::Entry> fibTelia = fib.insert("/telia").first;
737 fibTelia->addNextHop(face2, 10);
738 shared_ptr<fib::Entry> fibUcla = fib.insert("/ucla").first;
739 fibUcla->addNextHop(face2, 10);
740
741 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
742 interest2->setLink(link->wireEncode());
743 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
744 pit2->insertOrUpdateInRecord(face1, *interest2);
745
746 forwarder.onContentStoreMiss(*face1, pit2, *interest2);
747 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/telia");
748 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
749 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
750
751 fib.erase(*fibTelia);
752 fib.erase(*fibUcla);
753
754 // first default-free router, only second delegation is available
755 nrt.clear();
756 nrt.insert("/arizona/cs/hobo");
757 fibUcla = fib.insert("/ucla").first;
758 fibUcla->addNextHop(face2, 10);
759
760 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
761 interest3->setLink(link->wireEncode());
762 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
763 pit3->insertOrUpdateInRecord(face1, *interest3);
764
765 forwarder.onContentStoreMiss(*face1, pit3, *interest3);
766 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
767 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
768 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
769
770 fib.erase(*fibUcla);
771
772 // default-free router, chosen SelectedDelegation
773 nrt.clear();
774 nrt.insert("/ucsd/caida/click");
775 fibTelia = fib.insert("/telia").first;
776 fibTelia->addNextHop(face2, 10);
777 fibUcla = fib.insert("/ucla").first;
778 fibUcla->addNextHop(face2, 10);
779
780 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
781 interest4->setLink(link->wireEncode());
782 interest4->setSelectedDelegation("/ucla/cs");
783 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
784 pit4->insertOrUpdateInRecord(face1, *interest4);
785
786 forwarder.onContentStoreMiss(*face1, pit4, *interest4);
787 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/ucla");
788 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
789 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
790
791 fib.erase(*fibTelia);
792 fib.erase(*fibUcla);
793
794 // producer region
795 nrt.clear();
796 nrt.insert("/ucla/cs/spurs");
797 fibRoot->addNextHop(face2, 10);
798 fibUcla = fib.insert("/ucla").first;
799 fibUcla->addNextHop(face2, 10);
800 shared_ptr<fib::Entry> fibNdnsim = fib.insert("/net/ndnsim").first;
801 fibNdnsim->addNextHop(face2, 10);
802
803 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
804 interest5->setLink(link->wireEncode());
805 interest5->setSelectedDelegation("/ucla/cs");
806 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
807 pit5->insertOrUpdateInRecord(face1, *interest5);
808
809 forwarder.onContentStoreMiss(*face1, pit5, *interest5);
810 BOOST_CHECK_EQUAL(getLastFibPrefix(), "/net/ndnsim");
811 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
812 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
813
814 fibRoot->removeNextHop(face2);
815 fib.erase(*fibUcla);
816 fib.erase(*fibNdnsim);
817}
818
819
820class MalformedPacketFixture : public UnitTestTimeFixture
821{
822protected:
823 MalformedPacketFixture()
824 : face1(make_shared<DummyFace>())
825 , face2(make_shared<DummyFace>())
826 {
827 forwarder.addFace(face1);
828 forwarder.addFace(face2);
829 }
830
831 void
832 processInterest(shared_ptr<Interest> badInterest)
833 {
834 forwarder.startProcessInterest(*face1, *badInterest);
835 this->continueProcessPacket();
836 }
837
838 // processData
839
840 // processNack
841
842private:
843 void
844 continueProcessPacket()
845 {
846 this->advanceClocks(time::milliseconds(10), time::seconds(6));
847 }
848
849protected:
850 Forwarder forwarder;
851 shared_ptr<DummyFace> face1; // face of incoming bad packet
852 shared_ptr<DummyFace> face2; // another face for setting up states
853};
854
855BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
856
857BOOST_AUTO_TEST_CASE(BadLink)
858{
859 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
860 Block wire = goodInterest->wireEncode();
861 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
862 wire.encode();
863
864 auto badInterest = make_shared<Interest>();
865 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
866 BOOST_REQUIRE(badInterest->hasLink());
867 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
868
869 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
870}
871
872BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
873
874BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700875BOOST_AUTO_TEST_SUITE_END()
876
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700877} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700878} // namespace nfd