blob: 7f2bc41db21d409093b446754ef51021dfb3f44c [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 Shia6de4292016-07-12 02:08:10 +000042 shared_ptr<Interest> interestAB = makeInterest("/A/B");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070043 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000044 shared_ptr<Data> dataABC = makeData("/A/B/C");
Junxiao Shi8c8d2182014-01-30 22:33:00 -070045
Junxiao Shicde37ad2015-12-24 01:02:05 -070046 auto face1 = make_shared<DummyFace>();
47 auto face2 = make_shared<DummyFace>();
Junxiao Shi8c8d2182014-01-30 22:33:00 -070048 forwarder.addFace(face1);
49 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070050
Junxiao Shi8c8d2182014-01-30 22:33:00 -070051 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000052 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070053
Junxiao Shida93f1f2015-11-11 06:13:16 -070054 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
55 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000056 face1->receiveInterest(*interestAB);
57 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070058 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000059 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -070060 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
61 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070062 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
63 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070064
Junxiao Shida93f1f2015-11-11 06:13:16 -070065 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
66 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000067 face2->receiveData(*dataABC);
68 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070069 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000070 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), "/A/B/C");
Junxiao Shicde37ad2015-12-24 01:02:05 -070071 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
72 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070073 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
74 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070075}
76
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070077BOOST_AUTO_TEST_CASE(CsMatched)
78{
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070079 Forwarder forwarder;
80
Junxiao Shicde37ad2015-12-24 01:02:05 -070081 auto face1 = make_shared<DummyFace>();
82 auto face2 = make_shared<DummyFace>();
83 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070084 forwarder.addFace(face1);
85 forwarder.addFace(face2);
86 forwarder.addFace(face3);
87
Junxiao Shia6de4292016-07-12 02:08:10 +000088 shared_ptr<Interest> interestA = makeInterest("/A");
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070089 interestA->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000090 shared_ptr<Data> dataA = makeData("/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +000091 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070092
93 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000094 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070095
96 Pit& pit = forwarder.getPit();
97 BOOST_CHECK_EQUAL(pit.size(), 0);
98
99 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700100 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700101
102 face1->receiveInterest(*interestA);
Junxiao Shid41d6072016-06-19 23:35:27 +0000103 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700104 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700105 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700106
Junxiao Shicde37ad2015-12-24 01:02:05 -0700107 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700108 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700109 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
110 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700111
Junxiao Shid41d6072016-06-19 23:35:27 +0000112 this->advanceClocks(time::milliseconds(100), time::milliseconds(500));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700113 // PIT entry should not be left behind
114 BOOST_CHECK_EQUAL(pit.size(), 0);
115}
116
Junxiao Shi891f47b2016-06-20 00:02:11 +0000117BOOST_AUTO_TEST_CASE(OutgoingInterest)
118{
119 Forwarder forwarder;
120 auto face1 = make_shared<DummyFace>();
121 auto face2 = make_shared<DummyFace>();
122 auto face3 = make_shared<DummyFace>();
123 forwarder.addFace(face1);
124 forwarder.addFace(face2);
125 forwarder.addFace(face3);
126
127 Pit& pit = forwarder.getPit();
Junxiao Shia6de4292016-07-12 02:08:10 +0000128 auto interestA1 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000129 interestA1->setNonce(8378);
130 shared_ptr<pit::Entry> pitA = pit.insert(*interestA1).first;
131 pit::InRecordCollection::iterator inA1 = pitA->insertOrUpdateInRecord(face1, *interestA1);
132
133 // there is only one downstream, interestA1 is used
134 forwarder.onOutgoingInterest(pitA, *face3, false);
135 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 1);
136 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 8378);
137
138 // new Nonce is requested
139 forwarder.onOutgoingInterest(pitA, *face3, true);
140 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 2);
141 BOOST_CHECK_NE(face3->sentInterests.back().getNonce(), 8378);
142 // Nonce on in-record Interest shouldn't be touched
143 BOOST_CHECK_EQUAL(inA1->getInterest().getNonce(), 8378);
144
145 // outgoing face is face1, interestA1 is still used because there's no other choice
146 forwarder.onOutgoingInterest(pitA, *face1, false);
147 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 1);
148 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 8378);
149
150 this->advanceClocks(time::seconds(2));
Junxiao Shia6de4292016-07-12 02:08:10 +0000151 auto interestA2 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000152 interestA2->setNonce(9102);
153 pitA->insertOrUpdateInRecord(face2, *interestA2);
154
155 // there are two downstreams, prefer newer interestA2
156 forwarder.onOutgoingInterest(pitA, *face3, false);
157 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 3);
158 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 9102);
159
160 // outgoing face is face2, prefer interestA1 from face1 despite it's older
161 forwarder.onOutgoingInterest(pitA, *face2, false);
162 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
163 BOOST_CHECK_EQUAL(face2->sentInterests.back().getNonce(), 8378);
164
165 // outgoing face is face1, prefer interestA2
166 forwarder.onOutgoingInterest(pitA, *face1, false);
167 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 2);
168 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 9102);
169}
170
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700171class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700172{
173public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700174 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700175 {
176 }
177
178 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200179 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700180 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700181 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700182 }
183
184protected:
185 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200186 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) override
Junxiao Shi88884492014-02-15 15:57:43 -0700187 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700188 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700189 }
190
191public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700192 int dispatchToStrategy_count;
193 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700194};
195
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700196BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700197{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700198 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700199 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
200 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700201 forwarder.addFace(face1);
202 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700203
Junxiao Shi88884492014-02-15 15:57:43 -0700204 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700205 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700206 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800207 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700208 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700209
Junxiao Shi88884492014-02-15 15:57:43 -0700210 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700211 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700212 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800213 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700214 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700215
Junxiao Shi88884492014-02-15 15:57:43 -0700216 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700217 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700218 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800219 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700220 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700221
Junxiao Shi88884492014-02-15 15:57:43 -0700222 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700223 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700224 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800225 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700226 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700227
Junxiao Shi88884492014-02-15 15:57:43 -0700228 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700229 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700230 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800231 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700232 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700233
234 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700235 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700236 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800237 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700238 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700239
Junxiao Shi88884492014-02-15 15:57:43 -0700240 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700241 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700242 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800243 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700244 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700245
246 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700247 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700248 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800249 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700250 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700251}
252
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700253BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
254{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700255 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700256 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
257 auto face2 = make_shared<DummyFace>();
258 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700259 forwarder.addFace(face1);
260 forwarder.addFace(face2);
261 forwarder.addFace(face3);
262 Pit& pit = forwarder.getPit();
263
264 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700265 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
266 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
267 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700268 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700269 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700270 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700271
272 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700273 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
274 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
275 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700276 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700277 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700278 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700279
280 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700281 shared_ptr<Interest> interestA3 = makeInterest("/A3");
282 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
283 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700284 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700285 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700286 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700287
288 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700289 shared_ptr<Interest> interestA4 = makeInterest("/A4");
290 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
291 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700292 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700293 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700294 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700295
296 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700297 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700298 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700299 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700300
301 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700302 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700303 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700304 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700305
306 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700307 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700308 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700309 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700310
311 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700312 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700313 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700314 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700315}
316
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700317BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
318{
319 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700320 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
321 auto face2 = make_shared<DummyFace>();
322 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
323 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700324 forwarder.addFace(face1);
325 forwarder.addFace(face2);
326 forwarder.addFace(face3);
327 forwarder.addFace(face4);
328 Pit& pit = forwarder.getPit();
329
330 // from local face, to local face: OK
331 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
332 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
333 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700334 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700335 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700336 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700337
338 // from non-local face, to local face: OK
339 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
340 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
341 pit2->insertOrUpdateInRecord(face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700342 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700343 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700344 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700345
346 // from local face, to non-local face: OK
347 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
348 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
349 pit3->insertOrUpdateInRecord(face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700350 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700351 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700352 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700353
354 // from non-local face, to non-local face: violate
355 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
356 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
357 pit4->insertOrUpdateInRecord(face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700358 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700359 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700360 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700361
362 // from local face and non-local face, to local face: OK
363 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
364 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
365 pit5->insertOrUpdateInRecord(face1, *interest5);
366 pit5->insertOrUpdateInRecord(face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700367 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700368 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700369 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700370
371 // from local face and non-local face, to non-local face: OK
372 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
373 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
374 pit6->insertOrUpdateInRecord(face1, *interest6);
375 pit6->insertOrUpdateInRecord(face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700376 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700377 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700378 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700379}
380
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700381BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700382{
Junxiao Shif3c07812014-03-11 21:48:49 -0700383 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700384 auto face1 = make_shared<DummyFace>();
385 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700386 forwarder.addFace(face1);
387 forwarder.addFace(face2);
388
389 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
390 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700391 ref(forwarder), "ndn:/strategyP");
Junxiao Shif3c07812014-03-11 21:48:49 -0700392 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700393 ref(forwarder), "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700394 strategyChoice.install(strategyP);
395 strategyChoice.install(strategyQ);
396 strategyChoice.insert("ndn:/" , strategyP->getName());
397 strategyChoice.insert("ndn:/B", strategyQ->getName());
398
399 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700400 strategyP->afterReceiveInterest_count = 0;
401 strategyP->interestOutFace = face2;
402 forwarder.startProcessInterest(*face1, *interest1);
403 BOOST_CHECK_EQUAL(strategyP->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700404
405 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700406 strategyQ->afterReceiveInterest_count = 0;
407 strategyQ->interestOutFace = face2;
408 forwarder.startProcessInterest(*face1, *interest2);
409 BOOST_CHECK_EQUAL(strategyQ->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700410
Junxiao Shid41d6072016-06-19 23:35:27 +0000411 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700412
413 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700414 strategyP->beforeSatisfyInterest_count = 0;
415 forwarder.startProcessData(*face2, *data1);
416 BOOST_CHECK_EQUAL(strategyP->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700417
418 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700419 strategyQ->beforeSatisfyInterest_count = 0;
420 forwarder.startProcessData(*face2, *data2);
421 BOOST_CHECK_EQUAL(strategyQ->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700422
423 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700424 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700425 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700426 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700427 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700428 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700429
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700430 strategyP->beforeExpirePendingInterest_count = 0;
431 strategyQ->beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000432 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700433 BOOST_CHECK_EQUAL(strategyP->beforeExpirePendingInterest_count, 1);
434 BOOST_CHECK_EQUAL(strategyQ->beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700435}
436
Junxiao Shida006f52014-05-16 11:18:00 -0700437BOOST_AUTO_TEST_CASE(IncomingData)
438{
Junxiao Shida006f52014-05-16 11:18:00 -0700439 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700440 auto face1 = make_shared<DummyFace>();
441 auto face2 = make_shared<DummyFace>();
442 auto face3 = make_shared<DummyFace>();
443 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700444 forwarder.addFace(face1);
445 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700446 forwarder.addFace(face3);
447 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700448
449 Pit& pit = forwarder.getPit();
450 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
451 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
452 pit0->insertOrUpdateInRecord(face1, *interest0);
453 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
454 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
455 pitA->insertOrUpdateInRecord(face1, *interestA);
456 pitA->insertOrUpdateInRecord(face2, *interestA);
457 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
458 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
459 pitC->insertOrUpdateInRecord(face3, *interestC);
460 pitC->insertOrUpdateInRecord(face4, *interestC);
461
462 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
463 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000464 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700465
Junxiao Shicde37ad2015-12-24 01:02:05 -0700466 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
467 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
468 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
469 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700470}
471
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700472BOOST_AUTO_TEST_CASE(IncomingNack)
473{
474 Forwarder forwarder;
475 auto face1 = make_shared<DummyFace>();
476 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700477 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
478 ndn::nfd::FACE_SCOPE_NON_LOCAL,
479 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
480 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700481 forwarder.addFace(face1);
482 forwarder.addFace(face2);
483 forwarder.addFace(face3);
484
485 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
486 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
487 ref(forwarder), "ndn:/strategyP");
488 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
489 ref(forwarder), "ndn:/strategyQ");
490 strategyChoice.install(strategyP);
491 strategyChoice.install(strategyQ);
492 strategyChoice.insert("ndn:/" , strategyP->getName());
493 strategyChoice.insert("ndn:/B", strategyQ->getName());
494
495 Pit& pit = forwarder.getPit();
496
497 // dispatch to the correct strategy
498 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
499 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
500 pit1->insertOrUpdateOutRecord(face1, *interest1);
501 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
502 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
503 pit2->insertOrUpdateOutRecord(face1, *interest2);
504
505 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
506 strategyP->afterReceiveNack_count = 0;
507 strategyQ->afterReceiveNack_count = 0;
508 forwarder.onIncomingNack(*face1, nack1);
509 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 1);
510 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
511
512 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
513 strategyP->afterReceiveNack_count = 0;
514 strategyQ->afterReceiveNack_count = 0;
515 forwarder.onIncomingNack(*face1, nack2);
516 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
517 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 1);
518
519 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700520 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
521 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700522 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
523 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
524
525 // drop if no PIT entry
526 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
527 strategyP->afterReceiveNack_count = 0;
528 strategyQ->afterReceiveNack_count = 0;
529 forwarder.onIncomingNack(*face1, nack3);
530 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
531 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
532
533 // drop if no out-record
534 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
535 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
536 pit4->insertOrUpdateOutRecord(face1, *interest4);
537
538 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
539 strategyP->afterReceiveNack_count = 0;
540 strategyQ->afterReceiveNack_count = 0;
541 forwarder.onIncomingNack(*face2, nack4a);
542 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
543 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
544
545 // drop if Nonce does not match out-record
546 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
547 strategyP->afterReceiveNack_count = 0;
548 strategyQ->afterReceiveNack_count = 0;
549 forwarder.onIncomingNack(*face1, nack4b);
550 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
551 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
552
553 // drop if inFace is multi-access
554 pit4->insertOrUpdateOutRecord(face3, *interest4);
555 strategyP->afterReceiveNack_count = 0;
556 strategyQ->afterReceiveNack_count = 0;
557 forwarder.onIncomingNack(*face3, nack4a);
558 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
559 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
560}
561
562BOOST_AUTO_TEST_CASE(OutgoingNack)
563{
564 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700565 auto face1 = make_shared<DummyFace>();
566 auto face2 = make_shared<DummyFace>();
567 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
568 ndn::nfd::FACE_SCOPE_NON_LOCAL,
569 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
570 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
571 forwarder.addFace(face1);
572 forwarder.addFace(face2);
573 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700574
575 Pit& pit = forwarder.getPit();
576
577 lp::NackHeader nackHeader;
578 nackHeader.setReason(lp::NackReason::CONGESTION);
579
580 // don't send Nack if there's no in-record
581 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
582 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700583 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700584
585 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700586 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700587 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
588
589 // send Nack with correct Nonce
590 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
591 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700592 pit2->insertOrUpdateInRecord(face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700593 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700594 pit2->insertOrUpdateInRecord(face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700595
596 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700597 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700598 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
599 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
600 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
601
602 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700603 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
604 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700605
606 // send Nack with correct Nonce
607 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700608 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700609 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
610 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
611 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
612
613 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700614 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
615 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700616
617 // don't send Nack to multi-access face
618 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700619 pit2->insertOrUpdateInRecord(face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700620
621 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700622 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700623 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
624}
625
626BOOST_AUTO_TEST_CASE(InterestLoopNack)
627{
628 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700629 auto face1 = make_shared<DummyFace>();
630 auto face2 = make_shared<DummyFace>();
631 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
632 ndn::nfd::FACE_SCOPE_NON_LOCAL,
633 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
634 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700635 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700636 forwarder.addFace(face1);
637 forwarder.addFace(face2);
638 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700639 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700640
641 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000642 fib.insert("/zT4XwK0Hnx").first->addNextHop(*face4, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700643
644 // receive Interest on face1
645 face1->sentNacks.clear();
646 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
647 face1->receiveInterest(*interest1a);
648 BOOST_CHECK(face1->sentNacks.empty());
649
650 // receive Interest with duplicate Nonce on face1
651 face1->sentNacks.clear();
652 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
653 face1->receiveInterest(*interest1b);
654 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
655 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
656 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
657
658 // receive Interest with duplicate Nonce on face2
659 face2->sentNacks.clear();
660 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
661 face2->receiveInterest(*interest2a);
662 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
663 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
664 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
665
666 // receive Interest with new Nonce on face2
667 face2->sentNacks.clear();
668 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
669 face2->receiveInterest(*interest2b);
670 BOOST_CHECK(face2->sentNacks.empty());
671
672 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
673 face3->sentNacks.clear();
674 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
675 face3->receiveInterest(*interest3a);
676 BOOST_CHECK(face3->sentNacks.empty());
677}
678
Junxiao Shi455581d2014-11-17 18:38:40 -0700679BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700680{
Junxiao Shia110f262014-10-12 12:35:20 -0700681 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700682 auto face1 = make_shared<DummyFace>();
683 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700684 forwarder.addFace(face1);
685 forwarder.addFace(face2);
686
687 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700688 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
689 if (pktType == tlv::Interest) {
690 auto interest = make_shared<Interest>(face2->sentInterests.back());
691 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
692 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700693 });
Junxiao Shia110f262014-10-12 12:35:20 -0700694
695 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000696 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shia110f262014-10-12 12:35:20 -0700697
Junxiao Shi455581d2014-11-17 18:38:40 -0700698 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700699 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
700 interest->setNonce(82101183);
701 interest->setInterestLifetime(time::milliseconds(50));
702 face1->receiveInterest(*interest);
703
Junxiao Shi455581d2014-11-17 18:38:40 -0700704 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
705 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
706 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700707
Junxiao Shicde37ad2015-12-24 01:02:05 -0700708 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700709
710 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
711 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
712 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
713 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
714 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700715}
716
Junxiao Shid41d6072016-06-19 23:35:27 +0000717BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700718{
719 Forwarder forwarder;
720 shared_ptr<Face> face1 = make_shared<DummyFace>();
721 forwarder.addFace(face1);
722
723 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
724 interest->setNonce(61883075);
725 interest->setInterestLifetime(time::seconds(2));
726
727 DeadNonceList& dnl = forwarder.getDeadNonceList();
728 dnl.add(interest->getName(), interest->getNonce());
729 Pit& pit = forwarder.getPit();
730 BOOST_REQUIRE_EQUAL(pit.size(), 0);
731
732 forwarder.startProcessInterest(*face1, *interest);
733 this->advanceClocks(time::milliseconds(100), time::seconds(20));
734 BOOST_CHECK_EQUAL(pit.size(), 0);
735}
736
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700737BOOST_AUTO_TEST_CASE(LinkDelegation)
738{
739 Forwarder forwarder;
740 shared_ptr<Face> face1 = make_shared<DummyFace>();
741 shared_ptr<Face> face2 = make_shared<DummyFace>();
742 forwarder.addFace(face1);
743 forwarder.addFace(face2);
744
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700745 Fib& fib = forwarder.getFib();
746 Pit& pit = forwarder.getPit();
747 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
748
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700749 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
750
751 // consumer region
752 nrt.clear();
753 nrt.insert("/arizona/cs/avenir");
Junxiao Shia6de4292016-07-12 02:08:10 +0000754 fib.insert("/").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700755
756 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
757 interest1->setLink(link->wireEncode());
758 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
759 pit1->insertOrUpdateInRecord(face1, *interest1);
760
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000761 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700762 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
763
Junxiao Shia6de4292016-07-12 02:08:10 +0000764 fib.insert("/").first->removeNextHop(*face2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700765
766 // first default-free router, both delegations are available
767 nrt.clear();
768 nrt.insert("/arizona/cs/hobo");
Junxiao Shia6de4292016-07-12 02:08:10 +0000769 fib.insert("/telia").first->addNextHop(*face2, 10);
770 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700771
772 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
773 interest2->setLink(link->wireEncode());
774 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
775 pit2->insertOrUpdateInRecord(face1, *interest2);
776
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000777 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit2).getPrefix(), "/telia");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700778 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
779 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
780
Junxiao Shia6de4292016-07-12 02:08:10 +0000781 fib.erase("/telia");
782 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700783
784 // first default-free router, only second delegation is available
785 nrt.clear();
786 nrt.insert("/arizona/cs/hobo");
Junxiao Shia6de4292016-07-12 02:08:10 +0000787 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700788
789 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
790 interest3->setLink(link->wireEncode());
791 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
792 pit3->insertOrUpdateInRecord(face1, *interest3);
793
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000794 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit3).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700795 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
796 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
797
Junxiao Shia6de4292016-07-12 02:08:10 +0000798 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700799
800 // default-free router, chosen SelectedDelegation
801 nrt.clear();
802 nrt.insert("/ucsd/caida/click");
Junxiao Shia6de4292016-07-12 02:08:10 +0000803 fib.insert("/telia").first->addNextHop(*face2, 10);
804 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700805
806 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
807 interest4->setLink(link->wireEncode());
808 interest4->setSelectedDelegation("/ucla/cs");
809 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
810 pit4->insertOrUpdateInRecord(face1, *interest4);
811
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000812 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit4).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700813 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
814 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
815
Junxiao Shia6de4292016-07-12 02:08:10 +0000816 fib.erase("/telia");
817 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700818
819 // producer region
820 nrt.clear();
821 nrt.insert("/ucla/cs/spurs");
Junxiao Shia6de4292016-07-12 02:08:10 +0000822 fib.insert("/").first->addNextHop(*face2, 10);
823 fib.insert("/ucla").first->addNextHop(*face2, 10);
824 fib.insert("/net/ndnsim").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700825
826 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
827 interest5->setLink(link->wireEncode());
828 interest5->setSelectedDelegation("/ucla/cs");
829 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
830 pit5->insertOrUpdateInRecord(face1, *interest5);
831
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000832 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/net/ndnsim");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700833 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
834 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
835
Junxiao Shia6de4292016-07-12 02:08:10 +0000836 fib.insert("/").first->removeNextHop(*face2);
837 fib.erase("/ucla");
838 fib.erase("/ndnsim");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700839}
840
841
842class MalformedPacketFixture : public UnitTestTimeFixture
843{
844protected:
845 MalformedPacketFixture()
846 : face1(make_shared<DummyFace>())
847 , face2(make_shared<DummyFace>())
848 {
849 forwarder.addFace(face1);
850 forwarder.addFace(face2);
851 }
852
853 void
854 processInterest(shared_ptr<Interest> badInterest)
855 {
856 forwarder.startProcessInterest(*face1, *badInterest);
857 this->continueProcessPacket();
858 }
859
860 // processData
861
862 // processNack
863
864private:
865 void
866 continueProcessPacket()
867 {
868 this->advanceClocks(time::milliseconds(10), time::seconds(6));
869 }
870
871protected:
872 Forwarder forwarder;
873 shared_ptr<DummyFace> face1; // face of incoming bad packet
874 shared_ptr<DummyFace> face2; // another face for setting up states
875};
876
877BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
878
879BOOST_AUTO_TEST_CASE(BadLink)
880{
881 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
882 Block wire = goodInterest->wireEncode();
883 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
884 wire.encode();
885
886 auto badInterest = make_shared<Interest>();
887 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
888 BOOST_REQUIRE(badInterest->hasLink());
889 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
890
891 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
892}
893
894BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
895
896BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700897BOOST_AUTO_TEST_SUITE_END()
898
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700899} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700900} // namespace nfd