blob: 497952a7c6e293961b88d6e87f821461ccc16085 [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 Shi9b27bd22014-02-26 20:29:58 -0700173class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700174{
175public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700176 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700177 {
178 }
179
180 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200181 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700182 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700183 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700184 }
185
186protected:
187 virtual void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000188 dispatchToStrategy(pit::Entry& pitEntry, function<void(fw::Strategy&)> trigger) override
Junxiao Shi88884492014-02-15 15:57:43 -0700189 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700190 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700191 }
192
193public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700194 int dispatchToStrategy_count;
195 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700196};
197
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700198BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700199{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700200 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700201 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
202 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700203 forwarder.addFace(face1);
204 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700205
Junxiao Shi88884492014-02-15 15:57:43 -0700206 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700207 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700208 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800209 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700210 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700211
Junxiao Shi88884492014-02-15 15:57:43 -0700212 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700213 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700214 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800215 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700216 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700217
Junxiao Shi88884492014-02-15 15:57:43 -0700218 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700219 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700220 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800221 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700222 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700223
Junxiao Shi88884492014-02-15 15:57:43 -0700224 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700225 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700226 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800227 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700228 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
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.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700232 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800233 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700234 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700235
236 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700237 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700238 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800239 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700240 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_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.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700244 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800245 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700246 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700247
248 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700249 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700250 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800251 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700252 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700253}
254
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700255BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
256{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700257 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700258 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
259 auto face2 = make_shared<DummyFace>();
260 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700261 forwarder.addFace(face1);
262 forwarder.addFace(face2);
263 forwarder.addFace(face3);
264 Pit& pit = forwarder.getPit();
265
266 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700267 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
268 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000269 pitA1->insertOrUpdateInRecord(*face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700270 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700271 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700272 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700273
274 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700275 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
276 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000277 pitA2->insertOrUpdateInRecord(*face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700278 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700279 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700280 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700281
282 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700283 shared_ptr<Interest> interestA3 = makeInterest("/A3");
284 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000285 pitA3->insertOrUpdateInRecord(*face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700286 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700287 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700288 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700289
290 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700291 shared_ptr<Interest> interestA4 = makeInterest("/A4");
292 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000293 pitA4->insertOrUpdateInRecord(*face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700294 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700295 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700296 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700297
298 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700299 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700300 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700301 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700302
303 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700304 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700305 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700306 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700307
308 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700309 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700310 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700311 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700312
313 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700314 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700315 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700316 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700317}
318
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700319BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
320{
321 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700322 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
323 auto face2 = make_shared<DummyFace>();
324 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
325 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700326 forwarder.addFace(face1);
327 forwarder.addFace(face2);
328 forwarder.addFace(face3);
329 forwarder.addFace(face4);
330 Pit& pit = forwarder.getPit();
331
332 // from local face, to local face: OK
333 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
334 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000335 pit1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700336 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700337 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700338 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700339
340 // from non-local face, to local face: OK
341 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
342 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000343 pit2->insertOrUpdateInRecord(*face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700344 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700345 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700346 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700347
348 // from local face, to non-local face: OK
349 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
350 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000351 pit3->insertOrUpdateInRecord(*face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700352 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700353 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700354 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700355
356 // from non-local face, to non-local face: violate
357 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
358 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000359 pit4->insertOrUpdateInRecord(*face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700360 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700361 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700362 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700363
364 // from local face and non-local face, to local face: OK
365 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
366 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000367 pit5->insertOrUpdateInRecord(*face1, *interest5);
368 pit5->insertOrUpdateInRecord(*face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700369 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700370 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700371 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700372
373 // from local face and non-local face, to non-local face: OK
374 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
375 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000376 pit6->insertOrUpdateInRecord(*face1, *interest6);
377 pit6->insertOrUpdateInRecord(*face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700378 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700379 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700380 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700381}
382
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700383BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700384{
Junxiao Shif3c07812014-03-11 21:48:49 -0700385 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700386 auto face1 = make_shared<DummyFace>();
387 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700388 forwarder.addFace(face1);
389 forwarder.addFace(face2);
390
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000391 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
392 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700393
394 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000395 strategyP.afterReceiveInterest_count = 0;
396 strategyP.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700397 forwarder.startProcessInterest(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000398 BOOST_CHECK_EQUAL(strategyP.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700399
400 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000401 strategyQ.afterReceiveInterest_count = 0;
402 strategyQ.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700403 forwarder.startProcessInterest(*face1, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000404 BOOST_CHECK_EQUAL(strategyQ.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700405
Junxiao Shid41d6072016-06-19 23:35:27 +0000406 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700407
408 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000409 strategyP.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700410 forwarder.startProcessData(*face2, *data1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000411 BOOST_CHECK_EQUAL(strategyP.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700412
413 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000414 strategyQ.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700415 forwarder.startProcessData(*face2, *data2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000416 BOOST_CHECK_EQUAL(strategyQ.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700417
418 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700419 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700420 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700421 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700422 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700423 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700424
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000425 strategyP.beforeExpirePendingInterest_count = 0;
426 strategyQ.beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000427 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000428 BOOST_CHECK_EQUAL(strategyP.beforeExpirePendingInterest_count, 1);
429 BOOST_CHECK_EQUAL(strategyQ.beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700430}
431
Junxiao Shida006f52014-05-16 11:18:00 -0700432BOOST_AUTO_TEST_CASE(IncomingData)
433{
Junxiao Shida006f52014-05-16 11:18:00 -0700434 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700435 auto face1 = make_shared<DummyFace>();
436 auto face2 = make_shared<DummyFace>();
437 auto face3 = make_shared<DummyFace>();
438 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700439 forwarder.addFace(face1);
440 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700441 forwarder.addFace(face3);
442 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700443
444 Pit& pit = forwarder.getPit();
445 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
446 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000447 pit0->insertOrUpdateInRecord(*face1, *interest0);
Junxiao Shida006f52014-05-16 11:18:00 -0700448 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
449 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000450 pitA->insertOrUpdateInRecord(*face1, *interestA);
451 pitA->insertOrUpdateInRecord(*face2, *interestA);
Junxiao Shida006f52014-05-16 11:18:00 -0700452 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
453 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000454 pitC->insertOrUpdateInRecord(*face3, *interestC);
455 pitC->insertOrUpdateInRecord(*face4, *interestC);
Junxiao Shida006f52014-05-16 11:18:00 -0700456
457 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
458 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000459 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700460
Junxiao Shicde37ad2015-12-24 01:02:05 -0700461 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
462 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
463 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
464 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700465}
466
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700467BOOST_AUTO_TEST_CASE(IncomingNack)
468{
469 Forwarder forwarder;
470 auto face1 = make_shared<DummyFace>();
471 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700472 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
473 ndn::nfd::FACE_SCOPE_NON_LOCAL,
474 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
475 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700476 forwarder.addFace(face1);
477 forwarder.addFace(face2);
478 forwarder.addFace(face3);
479
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000480 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
481 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700482
483 Pit& pit = forwarder.getPit();
484
485 // dispatch to the correct strategy
486 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
487 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000488 pit1->insertOrUpdateOutRecord(*face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700489 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
490 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000491 pit2->insertOrUpdateOutRecord(*face1, *interest2);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700492
493 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000494 strategyP.afterReceiveNack_count = 0;
495 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700496 forwarder.onIncomingNack(*face1, nack1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000497 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 1);
498 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700499
500 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000501 strategyP.afterReceiveNack_count = 0;
502 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700503 forwarder.onIncomingNack(*face1, nack2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000504 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
505 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700506
507 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700508 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
509 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700510 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
511 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
512
513 // drop if no PIT entry
514 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000515 strategyP.afterReceiveNack_count = 0;
516 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700517 forwarder.onIncomingNack(*face1, nack3);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000518 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
519 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700520
521 // drop if no out-record
522 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
523 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000524 pit4->insertOrUpdateOutRecord(*face1, *interest4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700525
526 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000527 strategyP.afterReceiveNack_count = 0;
528 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700529 forwarder.onIncomingNack(*face2, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000530 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
531 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700532
533 // drop if Nonce does not match out-record
534 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000535 strategyP.afterReceiveNack_count = 0;
536 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700537 forwarder.onIncomingNack(*face1, nack4b);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000538 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
539 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700540
541 // drop if inFace is multi-access
Junxiao Shi9cff7792016-08-01 21:45:11 +0000542 pit4->insertOrUpdateOutRecord(*face3, *interest4);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000543 strategyP.afterReceiveNack_count = 0;
544 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700545 forwarder.onIncomingNack(*face3, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000546 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
547 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700548}
549
550BOOST_AUTO_TEST_CASE(OutgoingNack)
551{
552 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700553 auto face1 = make_shared<DummyFace>();
554 auto face2 = make_shared<DummyFace>();
555 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
556 ndn::nfd::FACE_SCOPE_NON_LOCAL,
557 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
558 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
559 forwarder.addFace(face1);
560 forwarder.addFace(face2);
561 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700562
563 Pit& pit = forwarder.getPit();
564
565 lp::NackHeader nackHeader;
566 nackHeader.setReason(lp::NackReason::CONGESTION);
567
568 // don't send Nack if there's no in-record
569 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
570 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000571 pit1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700572
573 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700574 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700575 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
576
577 // send Nack with correct Nonce
578 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
579 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shi9cff7792016-08-01 21:45:11 +0000580 pit2->insertOrUpdateInRecord(*face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700581 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shi9cff7792016-08-01 21:45:11 +0000582 pit2->insertOrUpdateInRecord(*face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700583
584 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700585 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700586 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
587 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
588 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
589
590 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700591 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
592 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700593
594 // send Nack with correct Nonce
595 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700596 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700597 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
598 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
599 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
600
601 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700602 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
603 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700604
605 // don't send Nack to multi-access face
606 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shi9cff7792016-08-01 21:45:11 +0000607 pit2->insertOrUpdateInRecord(*face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700608
609 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700610 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700611 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
612}
613
614BOOST_AUTO_TEST_CASE(InterestLoopNack)
615{
616 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700617 auto face1 = make_shared<DummyFace>();
618 auto face2 = make_shared<DummyFace>();
619 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
620 ndn::nfd::FACE_SCOPE_NON_LOCAL,
621 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
622 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700623 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700624 forwarder.addFace(face1);
625 forwarder.addFace(face2);
626 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700627 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700628
629 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000630 fib.insert("/zT4XwK0Hnx").first->addNextHop(*face4, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700631
632 // receive Interest on face1
633 face1->sentNacks.clear();
634 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
635 face1->receiveInterest(*interest1a);
636 BOOST_CHECK(face1->sentNacks.empty());
637
638 // receive Interest with duplicate Nonce on face1
639 face1->sentNacks.clear();
640 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
641 face1->receiveInterest(*interest1b);
642 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
643 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
644 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
645
646 // receive Interest with duplicate Nonce on face2
647 face2->sentNacks.clear();
648 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
649 face2->receiveInterest(*interest2a);
650 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
651 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
652 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
653
654 // receive Interest with new Nonce on face2
655 face2->sentNacks.clear();
656 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
657 face2->receiveInterest(*interest2b);
658 BOOST_CHECK(face2->sentNacks.empty());
659
660 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
661 face3->sentNacks.clear();
662 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
663 face3->receiveInterest(*interest3a);
664 BOOST_CHECK(face3->sentNacks.empty());
665}
666
Junxiao Shi455581d2014-11-17 18:38:40 -0700667BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700668{
Junxiao Shia110f262014-10-12 12:35:20 -0700669 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700670 auto face1 = make_shared<DummyFace>();
671 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700672 forwarder.addFace(face1);
673 forwarder.addFace(face2);
674
675 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700676 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
677 if (pktType == tlv::Interest) {
678 auto interest = make_shared<Interest>(face2->sentInterests.back());
679 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
680 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700681 });
Junxiao Shia110f262014-10-12 12:35:20 -0700682
683 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000684 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shia110f262014-10-12 12:35:20 -0700685
Junxiao Shi455581d2014-11-17 18:38:40 -0700686 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700687 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
688 interest->setNonce(82101183);
689 interest->setInterestLifetime(time::milliseconds(50));
690 face1->receiveInterest(*interest);
691
Junxiao Shi455581d2014-11-17 18:38:40 -0700692 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
693 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
694 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700695
Junxiao Shicde37ad2015-12-24 01:02:05 -0700696 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700697
698 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
699 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
700 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
701 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
702 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700703}
704
Junxiao Shid41d6072016-06-19 23:35:27 +0000705BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700706{
707 Forwarder forwarder;
708 shared_ptr<Face> face1 = make_shared<DummyFace>();
709 forwarder.addFace(face1);
710
711 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
712 interest->setNonce(61883075);
713 interest->setInterestLifetime(time::seconds(2));
714
715 DeadNonceList& dnl = forwarder.getDeadNonceList();
716 dnl.add(interest->getName(), interest->getNonce());
717 Pit& pit = forwarder.getPit();
718 BOOST_REQUIRE_EQUAL(pit.size(), 0);
719
720 forwarder.startProcessInterest(*face1, *interest);
721 this->advanceClocks(time::milliseconds(100), time::seconds(20));
722 BOOST_CHECK_EQUAL(pit.size(), 0);
723}
724
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700725
726class MalformedPacketFixture : public UnitTestTimeFixture
727{
728protected:
729 MalformedPacketFixture()
730 : face1(make_shared<DummyFace>())
731 , face2(make_shared<DummyFace>())
732 {
733 forwarder.addFace(face1);
734 forwarder.addFace(face2);
735 }
736
737 void
738 processInterest(shared_ptr<Interest> badInterest)
739 {
740 forwarder.startProcessInterest(*face1, *badInterest);
741 this->continueProcessPacket();
742 }
743
744 // processData
745
746 // processNack
747
748private:
749 void
750 continueProcessPacket()
751 {
752 this->advanceClocks(time::milliseconds(10), time::seconds(6));
753 }
754
755protected:
756 Forwarder forwarder;
757 shared_ptr<DummyFace> face1; // face of incoming bad packet
758 shared_ptr<DummyFace> face2; // another face for setting up states
759};
760
761BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
762
763BOOST_AUTO_TEST_CASE(BadLink)
764{
765 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
766 Block wire = goodInterest->wireEncode();
767 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
768 wire.encode();
769
770 auto badInterest = make_shared<Interest>();
771 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
772 BOOST_REQUIRE(badInterest->hasLink());
773 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
774
775 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
776}
777
778BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
779
780BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700781BOOST_AUTO_TEST_SUITE_END()
782
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700783} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700784} // namespace nfd