blob: 1b81f1fbf2517084d9f060b0c32ae294593fb3a8 [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 Shia49a1ab2016-07-15 18:24:36 +000029#include "install-strategy.hpp"
Junxiao Shicbc8e942016-09-06 03:17:45 +000030#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi8c8d2182014-01-30 22:33:00 -070031
Junxiao Shid9ee45c2014-02-27 15:38:11 -070032#include "tests/test-common.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070033
34namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070036
Junxiao Shi0355e9f2015-09-02 07:24:53 -070037BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shid41d6072016-06-19 23:35:27 +000038BOOST_FIXTURE_TEST_SUITE(TestForwarder, UnitTestTimeFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070039
Junxiao Shi8c8d2182014-01-30 22:33:00 -070040BOOST_AUTO_TEST_CASE(SimpleExchange)
41{
Junxiao Shic041ca32014-02-25 20:01:15 -070042 Forwarder forwarder;
43
Junxiao Shia6de4292016-07-12 02:08:10 +000044 shared_ptr<Interest> interestAB = makeInterest("/A/B");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070045 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000046 shared_ptr<Data> dataABC = makeData("/A/B/C");
Junxiao Shi8c8d2182014-01-30 22:33:00 -070047
Junxiao Shicde37ad2015-12-24 01:02:05 -070048 auto face1 = make_shared<DummyFace>();
49 auto face2 = make_shared<DummyFace>();
Junxiao Shi8c8d2182014-01-30 22:33:00 -070050 forwarder.addFace(face1);
51 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070052
Junxiao Shi8c8d2182014-01-30 22:33:00 -070053 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000054 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070055
Junxiao Shida93f1f2015-11-11 06:13:16 -070056 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
57 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000058 face1->receiveInterest(*interestAB);
59 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070060 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000061 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -070062 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
63 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070064 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
65 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070066
Junxiao Shida93f1f2015-11-11 06:13:16 -070067 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
68 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000069 face2->receiveData(*dataABC);
70 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070071 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000072 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), "/A/B/C");
Junxiao Shicde37ad2015-12-24 01:02:05 -070073 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
74 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070075 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
76 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070077}
78
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070079BOOST_AUTO_TEST_CASE(CsMatched)
80{
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070081 Forwarder forwarder;
82
Junxiao Shicde37ad2015-12-24 01:02:05 -070083 auto face1 = make_shared<DummyFace>();
84 auto face2 = make_shared<DummyFace>();
85 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070086 forwarder.addFace(face1);
87 forwarder.addFace(face2);
88 forwarder.addFace(face3);
89
Junxiao Shia6de4292016-07-12 02:08:10 +000090 shared_ptr<Interest> interestA = makeInterest("/A");
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070091 interestA->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000092 shared_ptr<Data> dataA = makeData("/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +000093 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070094
95 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000096 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070097
98 Pit& pit = forwarder.getPit();
99 BOOST_CHECK_EQUAL(pit.size(), 0);
100
101 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700102 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700103
104 face1->receiveInterest(*interestA);
Junxiao Shid41d6072016-06-19 23:35:27 +0000105 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700106 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700107 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700108
Junxiao Shicde37ad2015-12-24 01:02:05 -0700109 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700110 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700111 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
112 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700113
Junxiao Shid41d6072016-06-19 23:35:27 +0000114 this->advanceClocks(time::milliseconds(100), time::milliseconds(500));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700115 // PIT entry should not be left behind
116 BOOST_CHECK_EQUAL(pit.size(), 0);
117}
118
Junxiao Shi891f47b2016-06-20 00:02:11 +0000119BOOST_AUTO_TEST_CASE(OutgoingInterest)
120{
121 Forwarder forwarder;
122 auto face1 = make_shared<DummyFace>();
123 auto face2 = make_shared<DummyFace>();
124 auto face3 = make_shared<DummyFace>();
125 forwarder.addFace(face1);
126 forwarder.addFace(face2);
127 forwarder.addFace(face3);
128
129 Pit& pit = forwarder.getPit();
Junxiao Shia6de4292016-07-12 02:08:10 +0000130 auto interestA1 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000131 interestA1->setNonce(8378);
132 shared_ptr<pit::Entry> pitA = pit.insert(*interestA1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000133 pit::InRecordCollection::iterator inA1 = pitA->insertOrUpdateInRecord(*face1, *interestA1);
Junxiao Shi891f47b2016-06-20 00:02:11 +0000134
135 // there is only one downstream, interestA1 is used
136 forwarder.onOutgoingInterest(pitA, *face3, false);
137 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 1);
138 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 8378);
139
140 // new Nonce is requested
141 forwarder.onOutgoingInterest(pitA, *face3, true);
142 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 2);
143 BOOST_CHECK_NE(face3->sentInterests.back().getNonce(), 8378);
144 // Nonce on in-record Interest shouldn't be touched
145 BOOST_CHECK_EQUAL(inA1->getInterest().getNonce(), 8378);
146
147 // outgoing face is face1, interestA1 is still used because there's no other choice
148 forwarder.onOutgoingInterest(pitA, *face1, false);
149 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 1);
150 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 8378);
151
152 this->advanceClocks(time::seconds(2));
Junxiao Shia6de4292016-07-12 02:08:10 +0000153 auto interestA2 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000154 interestA2->setNonce(9102);
Junxiao Shi9cff7792016-08-01 21:45:11 +0000155 pitA->insertOrUpdateInRecord(*face2, *interestA2);
Junxiao Shi891f47b2016-06-20 00:02:11 +0000156
157 // there are two downstreams, prefer newer interestA2
158 forwarder.onOutgoingInterest(pitA, *face3, false);
159 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 3);
160 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 9102);
161
162 // outgoing face is face2, prefer interestA1 from face1 despite it's older
163 forwarder.onOutgoingInterest(pitA, *face2, false);
164 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
165 BOOST_CHECK_EQUAL(face2->sentInterests.back().getNonce(), 8378);
166
167 // outgoing face is face1, prefer interestA2
168 forwarder.onOutgoingInterest(pitA, *face1, false);
169 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 2);
170 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 9102);
171}
172
Junxiao Shie342e8d2016-09-18 16:48:00 +0000173BOOST_AUTO_TEST_CASE(NextHopFaceId)
174{
175 Forwarder forwarder;
176
177 auto face1 = make_shared<DummyFace>();
178 auto face2 = make_shared<DummyFace>();
179 auto face3 = make_shared<DummyFace>();
180 forwarder.addFace(face1);
181 forwarder.addFace(face2);
182 forwarder.addFace(face3);
183
184 Fib& fib = forwarder.getFib();
185 fib.insert("/A").first->addNextHop(*face3, 0);
186
187 shared_ptr<Interest> interest = makeInterest("/A/B");
188 interest->setTag(make_shared<lp::NextHopFaceIdTag>(face2->getId()));
189
190 face1->receiveInterest(*interest);
191 this->advanceClocks(time::milliseconds(100), time::seconds(1));
192 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 0);
193 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
194 BOOST_CHECK_EQUAL(face2->sentInterests.front().getName(), "/A/B");
195}
196
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700197class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700198{
199public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700200 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700201 {
202 }
203
204 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200205 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700206 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700207 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700208 }
209
210protected:
211 virtual void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000212 dispatchToStrategy(pit::Entry& pitEntry, function<void(fw::Strategy&)> trigger) override
Junxiao Shi88884492014-02-15 15:57:43 -0700213 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700214 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700215 }
216
217public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700218 int dispatchToStrategy_count;
219 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700220};
221
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700222BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700223{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700224 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700225 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
226 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700227 forwarder.addFace(face1);
228 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700229
Junxiao Shi88884492014-02-15 15:57:43 -0700230 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700231 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700232 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800233 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700234 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700235
Junxiao Shi88884492014-02-15 15:57:43 -0700236 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700237 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700238 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800239 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700240 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700241
Junxiao Shi88884492014-02-15 15:57:43 -0700242 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700243 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700244 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800245 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700246 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700247
Junxiao Shi88884492014-02-15 15:57:43 -0700248 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700249 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700250 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800251 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700252 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700253
Junxiao Shi88884492014-02-15 15:57:43 -0700254 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700255 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700256 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800257 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700258 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700259
260 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700261 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700262 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800263 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700264 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700265
Junxiao Shi88884492014-02-15 15:57:43 -0700266 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700267 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700268 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800269 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700270 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700271
272 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700273 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700274 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800275 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700276 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700277}
278
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700279BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
280{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700281 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700282 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
283 auto face2 = make_shared<DummyFace>();
284 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700285 forwarder.addFace(face1);
286 forwarder.addFace(face2);
287 forwarder.addFace(face3);
288 Pit& pit = forwarder.getPit();
289
290 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700291 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
292 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000293 pitA1->insertOrUpdateInRecord(*face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700294 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700295 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700296 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700297
298 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700299 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
300 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000301 pitA2->insertOrUpdateInRecord(*face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700302 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700303 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700304 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700305
306 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700307 shared_ptr<Interest> interestA3 = makeInterest("/A3");
308 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000309 pitA3->insertOrUpdateInRecord(*face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700310 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700311 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700312 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700313
314 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700315 shared_ptr<Interest> interestA4 = makeInterest("/A4");
316 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000317 pitA4->insertOrUpdateInRecord(*face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700318 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700319 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700320 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700321
322 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700323 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700324 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700325 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700326
327 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700328 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700329 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700330 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700331
332 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700333 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700334 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700335 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700336
337 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700338 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700339 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700340 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700341}
342
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700343BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
344{
345 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700346 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
347 auto face2 = make_shared<DummyFace>();
348 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
349 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700350 forwarder.addFace(face1);
351 forwarder.addFace(face2);
352 forwarder.addFace(face3);
353 forwarder.addFace(face4);
354 Pit& pit = forwarder.getPit();
355
356 // from local face, to local face: OK
357 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
358 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000359 pit1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700360 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700361 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700362 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700363
364 // from non-local face, to local face: OK
365 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
366 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000367 pit2->insertOrUpdateInRecord(*face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700368 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700369 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700370 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700371
372 // from local face, to non-local face: OK
373 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
374 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000375 pit3->insertOrUpdateInRecord(*face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700376 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700377 forwarder.onOutgoingInterest(pit3, *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 // from non-local face, to non-local face: violate
381 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
382 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000383 pit4->insertOrUpdateInRecord(*face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700384 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700385 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700386 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700387
388 // from local face and non-local face, to local face: OK
389 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
390 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000391 pit5->insertOrUpdateInRecord(*face1, *interest5);
392 pit5->insertOrUpdateInRecord(*face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700393 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700394 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700395 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700396
397 // from local face and non-local face, to non-local face: OK
398 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
399 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000400 pit6->insertOrUpdateInRecord(*face1, *interest6);
401 pit6->insertOrUpdateInRecord(*face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700402 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700403 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700404 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700405}
406
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700407BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700408{
Junxiao Shif3c07812014-03-11 21:48:49 -0700409 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700410 auto face1 = make_shared<DummyFace>();
411 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700412 forwarder.addFace(face1);
413 forwarder.addFace(face2);
414
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000415 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
416 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700417
418 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000419 strategyP.afterReceiveInterest_count = 0;
420 strategyP.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700421 forwarder.startProcessInterest(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000422 BOOST_CHECK_EQUAL(strategyP.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700423
424 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000425 strategyQ.afterReceiveInterest_count = 0;
426 strategyQ.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700427 forwarder.startProcessInterest(*face1, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000428 BOOST_CHECK_EQUAL(strategyQ.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700429
Junxiao Shid41d6072016-06-19 23:35:27 +0000430 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700431
432 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000433 strategyP.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700434 forwarder.startProcessData(*face2, *data1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000435 BOOST_CHECK_EQUAL(strategyP.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700436
437 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000438 strategyQ.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700439 forwarder.startProcessData(*face2, *data2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000440 BOOST_CHECK_EQUAL(strategyQ.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700441
442 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700443 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700444 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700445 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700446 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700447 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700448
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000449 strategyP.beforeExpirePendingInterest_count = 0;
450 strategyQ.beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000451 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000452 BOOST_CHECK_EQUAL(strategyP.beforeExpirePendingInterest_count, 1);
453 BOOST_CHECK_EQUAL(strategyQ.beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700454}
455
Junxiao Shida006f52014-05-16 11:18:00 -0700456BOOST_AUTO_TEST_CASE(IncomingData)
457{
Junxiao Shida006f52014-05-16 11:18:00 -0700458 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700459 auto face1 = make_shared<DummyFace>();
460 auto face2 = make_shared<DummyFace>();
461 auto face3 = make_shared<DummyFace>();
462 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700463 forwarder.addFace(face1);
464 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700465 forwarder.addFace(face3);
466 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700467
468 Pit& pit = forwarder.getPit();
469 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
470 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000471 pit0->insertOrUpdateInRecord(*face1, *interest0);
Junxiao Shida006f52014-05-16 11:18:00 -0700472 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
473 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000474 pitA->insertOrUpdateInRecord(*face1, *interestA);
475 pitA->insertOrUpdateInRecord(*face2, *interestA);
Junxiao Shida006f52014-05-16 11:18:00 -0700476 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
477 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000478 pitC->insertOrUpdateInRecord(*face3, *interestC);
479 pitC->insertOrUpdateInRecord(*face4, *interestC);
Junxiao Shida006f52014-05-16 11:18:00 -0700480
481 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
482 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000483 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700484
Junxiao Shicde37ad2015-12-24 01:02:05 -0700485 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
486 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
487 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
488 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700489}
490
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700491BOOST_AUTO_TEST_CASE(IncomingNack)
492{
493 Forwarder forwarder;
494 auto face1 = make_shared<DummyFace>();
495 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700496 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
497 ndn::nfd::FACE_SCOPE_NON_LOCAL,
498 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
499 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700500 forwarder.addFace(face1);
501 forwarder.addFace(face2);
502 forwarder.addFace(face3);
503
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000504 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
505 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700506
507 Pit& pit = forwarder.getPit();
508
509 // dispatch to the correct strategy
510 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
511 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000512 pit1->insertOrUpdateOutRecord(*face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700513 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
514 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000515 pit2->insertOrUpdateOutRecord(*face1, *interest2);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700516
517 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000518 strategyP.afterReceiveNack_count = 0;
519 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700520 forwarder.onIncomingNack(*face1, nack1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000521 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 1);
522 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700523
524 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000525 strategyP.afterReceiveNack_count = 0;
526 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700527 forwarder.onIncomingNack(*face1, nack2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000528 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
529 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700530
531 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700532 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
533 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700534 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
535 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
536
537 // drop if no PIT entry
538 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000539 strategyP.afterReceiveNack_count = 0;
540 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700541 forwarder.onIncomingNack(*face1, nack3);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000542 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
543 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700544
545 // drop if no out-record
546 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
547 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000548 pit4->insertOrUpdateOutRecord(*face1, *interest4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700549
550 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000551 strategyP.afterReceiveNack_count = 0;
552 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700553 forwarder.onIncomingNack(*face2, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000554 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
555 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700556
557 // drop if Nonce does not match out-record
558 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000559 strategyP.afterReceiveNack_count = 0;
560 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700561 forwarder.onIncomingNack(*face1, nack4b);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000562 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
563 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700564
565 // drop if inFace is multi-access
Junxiao Shi9cff7792016-08-01 21:45:11 +0000566 pit4->insertOrUpdateOutRecord(*face3, *interest4);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000567 strategyP.afterReceiveNack_count = 0;
568 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700569 forwarder.onIncomingNack(*face3, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000570 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
571 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700572}
573
574BOOST_AUTO_TEST_CASE(OutgoingNack)
575{
576 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700577 auto face1 = make_shared<DummyFace>();
578 auto face2 = make_shared<DummyFace>();
579 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
580 ndn::nfd::FACE_SCOPE_NON_LOCAL,
581 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
582 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
583 forwarder.addFace(face1);
584 forwarder.addFace(face2);
585 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700586
587 Pit& pit = forwarder.getPit();
588
589 lp::NackHeader nackHeader;
590 nackHeader.setReason(lp::NackReason::CONGESTION);
591
592 // don't send Nack if there's no in-record
593 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
594 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000595 pit1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700596
597 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700598 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700599 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
600
601 // send Nack with correct Nonce
602 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
603 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000604 pit2->insertOrUpdateInRecord(*face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700605 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shi9cff7792016-08-01 21:45:11 +0000606 pit2->insertOrUpdateInRecord(*face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700607
608 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700609 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700610 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
611 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
612 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
613
614 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700615 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
616 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700617
618 // send Nack with correct Nonce
619 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700620 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700621 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
622 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
623 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
624
625 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700626 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
627 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700628
629 // don't send Nack to multi-access face
630 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shi9cff7792016-08-01 21:45:11 +0000631 pit2->insertOrUpdateInRecord(*face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700632
633 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700634 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700635 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
636}
637
638BOOST_AUTO_TEST_CASE(InterestLoopNack)
639{
640 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700641 auto face1 = make_shared<DummyFace>();
642 auto face2 = make_shared<DummyFace>();
643 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
644 ndn::nfd::FACE_SCOPE_NON_LOCAL,
645 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
646 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700647 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700648 forwarder.addFace(face1);
649 forwarder.addFace(face2);
650 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700651 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700652
653 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000654 fib.insert("/zT4XwK0Hnx").first->addNextHop(*face4, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700655
656 // receive Interest on face1
657 face1->sentNacks.clear();
658 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
659 face1->receiveInterest(*interest1a);
660 BOOST_CHECK(face1->sentNacks.empty());
661
662 // receive Interest with duplicate Nonce on face1
663 face1->sentNacks.clear();
664 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
665 face1->receiveInterest(*interest1b);
666 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
667 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
668 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
669
670 // receive Interest with duplicate Nonce on face2
671 face2->sentNacks.clear();
672 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
673 face2->receiveInterest(*interest2a);
674 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
675 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
676 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
677
678 // receive Interest with new Nonce on face2
679 face2->sentNacks.clear();
680 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
681 face2->receiveInterest(*interest2b);
682 BOOST_CHECK(face2->sentNacks.empty());
683
684 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
685 face3->sentNacks.clear();
686 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
687 face3->receiveInterest(*interest3a);
688 BOOST_CHECK(face3->sentNacks.empty());
689}
690
Junxiao Shi455581d2014-11-17 18:38:40 -0700691BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700692{
Junxiao Shia110f262014-10-12 12:35:20 -0700693 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700694 auto face1 = make_shared<DummyFace>();
695 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700696 forwarder.addFace(face1);
697 forwarder.addFace(face2);
698
699 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700700 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
701 if (pktType == tlv::Interest) {
702 auto interest = make_shared<Interest>(face2->sentInterests.back());
703 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
704 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700705 });
Junxiao Shia110f262014-10-12 12:35:20 -0700706
707 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000708 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shia110f262014-10-12 12:35:20 -0700709
Junxiao Shi455581d2014-11-17 18:38:40 -0700710 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700711 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
712 interest->setNonce(82101183);
713 interest->setInterestLifetime(time::milliseconds(50));
714 face1->receiveInterest(*interest);
715
Junxiao Shi455581d2014-11-17 18:38:40 -0700716 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
717 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
718 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700719
Junxiao Shicde37ad2015-12-24 01:02:05 -0700720 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700721
722 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
723 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
724 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
725 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
726 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700727}
728
Junxiao Shid41d6072016-06-19 23:35:27 +0000729BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700730{
731 Forwarder forwarder;
732 shared_ptr<Face> face1 = make_shared<DummyFace>();
733 forwarder.addFace(face1);
734
735 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
736 interest->setNonce(61883075);
737 interest->setInterestLifetime(time::seconds(2));
738
739 DeadNonceList& dnl = forwarder.getDeadNonceList();
740 dnl.add(interest->getName(), interest->getNonce());
741 Pit& pit = forwarder.getPit();
742 BOOST_REQUIRE_EQUAL(pit.size(), 0);
743
744 forwarder.startProcessInterest(*face1, *interest);
745 this->advanceClocks(time::milliseconds(100), time::seconds(20));
746 BOOST_CHECK_EQUAL(pit.size(), 0);
747}
748
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700749
750class MalformedPacketFixture : public UnitTestTimeFixture
751{
752protected:
753 MalformedPacketFixture()
754 : face1(make_shared<DummyFace>())
755 , face2(make_shared<DummyFace>())
756 {
757 forwarder.addFace(face1);
758 forwarder.addFace(face2);
759 }
760
761 void
762 processInterest(shared_ptr<Interest> badInterest)
763 {
764 forwarder.startProcessInterest(*face1, *badInterest);
765 this->continueProcessPacket();
766 }
767
768 // processData
769
770 // processNack
771
772private:
773 void
774 continueProcessPacket()
775 {
776 this->advanceClocks(time::milliseconds(10), time::seconds(6));
777 }
778
779protected:
780 Forwarder forwarder;
781 shared_ptr<DummyFace> face1; // face of incoming bad packet
782 shared_ptr<DummyFace> face2; // another face for setting up states
783};
784
785BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
786
787BOOST_AUTO_TEST_CASE(BadLink)
788{
789 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
790 Block wire = goodInterest->wireEncode();
791 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
792 wire.encode();
793
794 auto badInterest = make_shared<Interest>();
795 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
796 BOOST_REQUIRE(badInterest->hasLink());
797 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
798
799 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
800}
801
802BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
803
804BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700805BOOST_AUTO_TEST_SUITE_END()
806
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700807} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700808} // namespace nfd