blob: ad2877efc444ee759965babeff89a01d57fd8efb [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 Shi8c8d2182014-01-30 22:33:00 -070030
Junxiao Shid9ee45c2014-02-27 15:38:11 -070031#include "tests/test-common.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070032
33namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070034namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070035
Junxiao Shi0355e9f2015-09-02 07:24:53 -070036BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shid41d6072016-06-19 23:35:27 +000037BOOST_FIXTURE_TEST_SUITE(TestForwarder, UnitTestTimeFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070038
Junxiao Shi8c8d2182014-01-30 22:33:00 -070039BOOST_AUTO_TEST_CASE(SimpleExchange)
40{
Junxiao Shic041ca32014-02-25 20:01:15 -070041 Forwarder forwarder;
42
Junxiao Shia6de4292016-07-12 02:08:10 +000043 shared_ptr<Interest> interestAB = makeInterest("/A/B");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070044 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000045 shared_ptr<Data> dataABC = makeData("/A/B/C");
Junxiao Shi8c8d2182014-01-30 22:33:00 -070046
Junxiao Shicde37ad2015-12-24 01:02:05 -070047 auto face1 = make_shared<DummyFace>();
48 auto face2 = make_shared<DummyFace>();
Junxiao Shi8c8d2182014-01-30 22:33:00 -070049 forwarder.addFace(face1);
50 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070051
Junxiao Shi8c8d2182014-01-30 22:33:00 -070052 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000053 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070054
Junxiao Shida93f1f2015-11-11 06:13:16 -070055 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
56 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000057 face1->receiveInterest(*interestAB);
58 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070059 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000060 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -070061 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
62 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070063 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
64 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070065
Junxiao Shida93f1f2015-11-11 06:13:16 -070066 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
67 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000068 face2->receiveData(*dataABC);
69 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070070 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000071 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), "/A/B/C");
Junxiao Shicde37ad2015-12-24 01:02:05 -070072 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
73 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070074 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
75 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070076}
77
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070078BOOST_AUTO_TEST_CASE(CsMatched)
79{
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070080 Forwarder forwarder;
81
Junxiao Shicde37ad2015-12-24 01:02:05 -070082 auto face1 = make_shared<DummyFace>();
83 auto face2 = make_shared<DummyFace>();
84 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070085 forwarder.addFace(face1);
86 forwarder.addFace(face2);
87 forwarder.addFace(face3);
88
Junxiao Shia6de4292016-07-12 02:08:10 +000089 shared_ptr<Interest> interestA = makeInterest("/A");
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070090 interestA->setInterestLifetime(time::seconds(4));
Junxiao Shia6de4292016-07-12 02:08:10 +000091 shared_ptr<Data> dataA = makeData("/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +000092 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070093
94 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +000095 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070096
97 Pit& pit = forwarder.getPit();
98 BOOST_CHECK_EQUAL(pit.size(), 0);
99
100 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700101 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700102
103 face1->receiveInterest(*interestA);
Junxiao Shid41d6072016-06-19 23:35:27 +0000104 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700105 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700106 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700107
Junxiao Shicde37ad2015-12-24 01:02:05 -0700108 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700109 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700110 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
111 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700112
Junxiao Shid41d6072016-06-19 23:35:27 +0000113 this->advanceClocks(time::milliseconds(100), time::milliseconds(500));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700114 // PIT entry should not be left behind
115 BOOST_CHECK_EQUAL(pit.size(), 0);
116}
117
Junxiao Shi891f47b2016-06-20 00:02:11 +0000118BOOST_AUTO_TEST_CASE(OutgoingInterest)
119{
120 Forwarder forwarder;
121 auto face1 = make_shared<DummyFace>();
122 auto face2 = make_shared<DummyFace>();
123 auto face3 = make_shared<DummyFace>();
124 forwarder.addFace(face1);
125 forwarder.addFace(face2);
126 forwarder.addFace(face3);
127
128 Pit& pit = forwarder.getPit();
Junxiao Shia6de4292016-07-12 02:08:10 +0000129 auto interestA1 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000130 interestA1->setNonce(8378);
131 shared_ptr<pit::Entry> pitA = pit.insert(*interestA1).first;
132 pit::InRecordCollection::iterator inA1 = pitA->insertOrUpdateInRecord(face1, *interestA1);
133
134 // there is only one downstream, interestA1 is used
135 forwarder.onOutgoingInterest(pitA, *face3, false);
136 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 1);
137 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 8378);
138
139 // new Nonce is requested
140 forwarder.onOutgoingInterest(pitA, *face3, true);
141 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 2);
142 BOOST_CHECK_NE(face3->sentInterests.back().getNonce(), 8378);
143 // Nonce on in-record Interest shouldn't be touched
144 BOOST_CHECK_EQUAL(inA1->getInterest().getNonce(), 8378);
145
146 // outgoing face is face1, interestA1 is still used because there's no other choice
147 forwarder.onOutgoingInterest(pitA, *face1, false);
148 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 1);
149 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 8378);
150
151 this->advanceClocks(time::seconds(2));
Junxiao Shia6de4292016-07-12 02:08:10 +0000152 auto interestA2 = makeInterest("/A");
Junxiao Shi891f47b2016-06-20 00:02:11 +0000153 interestA2->setNonce(9102);
154 pitA->insertOrUpdateInRecord(face2, *interestA2);
155
156 // there are two downstreams, prefer newer interestA2
157 forwarder.onOutgoingInterest(pitA, *face3, false);
158 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 3);
159 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 9102);
160
161 // outgoing face is face2, prefer interestA1 from face1 despite it's older
162 forwarder.onOutgoingInterest(pitA, *face2, false);
163 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
164 BOOST_CHECK_EQUAL(face2->sentInterests.back().getNonce(), 8378);
165
166 // outgoing face is face1, prefer interestA2
167 forwarder.onOutgoingInterest(pitA, *face1, false);
168 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 2);
169 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 9102);
170}
171
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700172class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700173{
174public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700175 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700176 {
177 }
178
179 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200180 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700181 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700182 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700183 }
184
185protected:
186 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200187 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) override
Junxiao Shi88884492014-02-15 15:57:43 -0700188 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700189 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700190 }
191
192public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700193 int dispatchToStrategy_count;
194 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700195};
196
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700197BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700198{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700199 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700200 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
201 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700202 forwarder.addFace(face1);
203 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700204
Junxiao Shi88884492014-02-15 15:57:43 -0700205 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700206 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700207 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800208 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700209 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700210
Junxiao Shi88884492014-02-15 15:57:43 -0700211 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700212 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700213 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800214 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700215 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700216
Junxiao Shi88884492014-02-15 15:57:43 -0700217 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700218 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700219 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800220 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700221 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700222
Junxiao Shi88884492014-02-15 15:57:43 -0700223 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700224 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700225 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800226 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700227 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700228
Junxiao Shi88884492014-02-15 15:57:43 -0700229 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700230 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700231 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800232 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700233 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700234
235 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700236 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700237 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800238 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700239 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700240
Junxiao Shi88884492014-02-15 15:57:43 -0700241 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700242 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700243 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800244 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700245 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700246
247 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700248 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700249 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800250 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700251 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700252}
253
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700254BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
255{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700256 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700257 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
258 auto face2 = make_shared<DummyFace>();
259 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700260 forwarder.addFace(face1);
261 forwarder.addFace(face2);
262 forwarder.addFace(face3);
263 Pit& pit = forwarder.getPit();
264
265 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700266 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
267 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
268 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700269 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700270 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700271 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700272
273 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700274 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
275 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
276 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700277 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700278 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700279 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700280
281 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700282 shared_ptr<Interest> interestA3 = makeInterest("/A3");
283 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
284 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700285 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700286 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700287 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700288
289 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700290 shared_ptr<Interest> interestA4 = makeInterest("/A4");
291 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
292 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700293 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700294 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700295 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700296
297 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700298 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700299 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700300 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700301
302 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700303 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700304 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700305 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700306
307 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700308 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700309 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700310 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700311
312 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700313 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700314 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700315 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700316}
317
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700318BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
319{
320 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700321 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
322 auto face2 = make_shared<DummyFace>();
323 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
324 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700325 forwarder.addFace(face1);
326 forwarder.addFace(face2);
327 forwarder.addFace(face3);
328 forwarder.addFace(face4);
329 Pit& pit = forwarder.getPit();
330
331 // from local face, to local face: OK
332 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
333 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
334 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700335 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700336 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700337 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700338
339 // from non-local face, to local face: OK
340 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
341 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
342 pit2->insertOrUpdateInRecord(face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700343 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700344 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700345 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700346
347 // from local face, to non-local face: OK
348 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
349 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
350 pit3->insertOrUpdateInRecord(face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700351 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700352 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700353 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700354
355 // from non-local face, to non-local face: violate
356 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
357 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
358 pit4->insertOrUpdateInRecord(face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700359 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700360 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700361 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700362
363 // from local face and non-local face, to local face: OK
364 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
365 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
366 pit5->insertOrUpdateInRecord(face1, *interest5);
367 pit5->insertOrUpdateInRecord(face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700368 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700369 forwarder.onOutgoingInterest(pit5, *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 and non-local face, to non-local face: OK
373 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
374 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
375 pit6->insertOrUpdateInRecord(face1, *interest6);
376 pit6->insertOrUpdateInRecord(face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700377 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700378 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700379 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700380}
381
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700382BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700383{
Junxiao Shif3c07812014-03-11 21:48:49 -0700384 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700385 auto face1 = make_shared<DummyFace>();
386 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700387 forwarder.addFace(face1);
388 forwarder.addFace(face2);
389
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000390 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
391 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700392
393 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000394 strategyP.afterReceiveInterest_count = 0;
395 strategyP.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700396 forwarder.startProcessInterest(*face1, *interest1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000397 BOOST_CHECK_EQUAL(strategyP.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700398
399 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000400 strategyQ.afterReceiveInterest_count = 0;
401 strategyQ.interestOutFace = face2;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700402 forwarder.startProcessInterest(*face1, *interest2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000403 BOOST_CHECK_EQUAL(strategyQ.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700404
Junxiao Shid41d6072016-06-19 23:35:27 +0000405 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700406
407 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000408 strategyP.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700409 forwarder.startProcessData(*face2, *data1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000410 BOOST_CHECK_EQUAL(strategyP.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700411
412 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000413 strategyQ.beforeSatisfyInterest_count = 0;
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700414 forwarder.startProcessData(*face2, *data2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000415 BOOST_CHECK_EQUAL(strategyQ.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700416
417 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700418 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700419 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700420 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700421 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700422 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700423
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000424 strategyP.beforeExpirePendingInterest_count = 0;
425 strategyQ.beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000426 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000427 BOOST_CHECK_EQUAL(strategyP.beforeExpirePendingInterest_count, 1);
428 BOOST_CHECK_EQUAL(strategyQ.beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700429}
430
Junxiao Shida006f52014-05-16 11:18:00 -0700431BOOST_AUTO_TEST_CASE(IncomingData)
432{
Junxiao Shida006f52014-05-16 11:18:00 -0700433 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700434 auto face1 = make_shared<DummyFace>();
435 auto face2 = make_shared<DummyFace>();
436 auto face3 = make_shared<DummyFace>();
437 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700438 forwarder.addFace(face1);
439 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700440 forwarder.addFace(face3);
441 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700442
443 Pit& pit = forwarder.getPit();
444 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
445 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
446 pit0->insertOrUpdateInRecord(face1, *interest0);
447 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
448 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
449 pitA->insertOrUpdateInRecord(face1, *interestA);
450 pitA->insertOrUpdateInRecord(face2, *interestA);
451 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
452 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
453 pitC->insertOrUpdateInRecord(face3, *interestC);
454 pitC->insertOrUpdateInRecord(face4, *interestC);
455
456 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
457 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000458 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700459
Junxiao Shicde37ad2015-12-24 01:02:05 -0700460 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
461 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
462 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
463 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700464}
465
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700466BOOST_AUTO_TEST_CASE(IncomingNack)
467{
468 Forwarder forwarder;
469 auto face1 = make_shared<DummyFace>();
470 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700471 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
472 ndn::nfd::FACE_SCOPE_NON_LOCAL,
473 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
474 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700475 forwarder.addFace(face1);
476 forwarder.addFace(face2);
477 forwarder.addFace(face3);
478
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000479 DummyStrategy& strategyP = choose<DummyStrategy>(forwarder, "ndn:/", "ndn:/strategyP");
480 DummyStrategy& strategyQ = choose<DummyStrategy>(forwarder, "ndn:/B", "ndn:/strategyQ");
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700481
482 Pit& pit = forwarder.getPit();
483
484 // dispatch to the correct strategy
485 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
486 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
487 pit1->insertOrUpdateOutRecord(face1, *interest1);
488 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
489 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
490 pit2->insertOrUpdateOutRecord(face1, *interest2);
491
492 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000493 strategyP.afterReceiveNack_count = 0;
494 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700495 forwarder.onIncomingNack(*face1, nack1);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000496 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 1);
497 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700498
499 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000500 strategyP.afterReceiveNack_count = 0;
501 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700502 forwarder.onIncomingNack(*face1, nack2);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000503 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
504 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700505
506 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700507 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
508 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700509 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
510 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
511
512 // drop if no PIT entry
513 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000514 strategyP.afterReceiveNack_count = 0;
515 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700516 forwarder.onIncomingNack(*face1, nack3);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000517 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
518 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700519
520 // drop if no out-record
521 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
522 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
523 pit4->insertOrUpdateOutRecord(face1, *interest4);
524
525 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000526 strategyP.afterReceiveNack_count = 0;
527 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700528 forwarder.onIncomingNack(*face2, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000529 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
530 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700531
532 // drop if Nonce does not match out-record
533 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000534 strategyP.afterReceiveNack_count = 0;
535 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700536 forwarder.onIncomingNack(*face1, nack4b);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000537 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
538 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700539
540 // drop if inFace is multi-access
541 pit4->insertOrUpdateOutRecord(face3, *interest4);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000542 strategyP.afterReceiveNack_count = 0;
543 strategyQ.afterReceiveNack_count = 0;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700544 forwarder.onIncomingNack(*face3, nack4a);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000545 BOOST_CHECK_EQUAL(strategyP.afterReceiveNack_count, 0);
546 BOOST_CHECK_EQUAL(strategyQ.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700547}
548
549BOOST_AUTO_TEST_CASE(OutgoingNack)
550{
551 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700552 auto face1 = make_shared<DummyFace>();
553 auto face2 = make_shared<DummyFace>();
554 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
555 ndn::nfd::FACE_SCOPE_NON_LOCAL,
556 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
557 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
558 forwarder.addFace(face1);
559 forwarder.addFace(face2);
560 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700561
562 Pit& pit = forwarder.getPit();
563
564 lp::NackHeader nackHeader;
565 nackHeader.setReason(lp::NackReason::CONGESTION);
566
567 // don't send Nack if there's no in-record
568 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
569 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700570 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700571
572 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700573 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700574 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
575
576 // send Nack with correct Nonce
577 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
578 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700579 pit2->insertOrUpdateInRecord(face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700580 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700581 pit2->insertOrUpdateInRecord(face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700582
583 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700584 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700585 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
586 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
587 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
588
589 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700590 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
591 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700592
593 // send Nack with correct Nonce
594 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700595 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700596 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
597 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
598 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
599
600 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700601 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
602 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700603
604 // don't send Nack to multi-access face
605 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700606 pit2->insertOrUpdateInRecord(face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700607
608 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700609 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700610 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
611}
612
613BOOST_AUTO_TEST_CASE(InterestLoopNack)
614{
615 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700616 auto face1 = make_shared<DummyFace>();
617 auto face2 = make_shared<DummyFace>();
618 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
619 ndn::nfd::FACE_SCOPE_NON_LOCAL,
620 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
621 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700622 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700623 forwarder.addFace(face1);
624 forwarder.addFace(face2);
625 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700626 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700627
628 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000629 fib.insert("/zT4XwK0Hnx").first->addNextHop(*face4, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700630
631 // receive Interest on face1
632 face1->sentNacks.clear();
633 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
634 face1->receiveInterest(*interest1a);
635 BOOST_CHECK(face1->sentNacks.empty());
636
637 // receive Interest with duplicate Nonce on face1
638 face1->sentNacks.clear();
639 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
640 face1->receiveInterest(*interest1b);
641 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
642 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
643 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
644
645 // receive Interest with duplicate Nonce on face2
646 face2->sentNacks.clear();
647 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
648 face2->receiveInterest(*interest2a);
649 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
650 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
651 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
652
653 // receive Interest with new Nonce on face2
654 face2->sentNacks.clear();
655 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
656 face2->receiveInterest(*interest2b);
657 BOOST_CHECK(face2->sentNacks.empty());
658
659 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
660 face3->sentNacks.clear();
661 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
662 face3->receiveInterest(*interest3a);
663 BOOST_CHECK(face3->sentNacks.empty());
664}
665
Junxiao Shi455581d2014-11-17 18:38:40 -0700666BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700667{
Junxiao Shia110f262014-10-12 12:35:20 -0700668 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700669 auto face1 = make_shared<DummyFace>();
670 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700671 forwarder.addFace(face1);
672 forwarder.addFace(face2);
673
674 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700675 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
676 if (pktType == tlv::Interest) {
677 auto interest = make_shared<Interest>(face2->sentInterests.back());
678 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
679 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700680 });
Junxiao Shia110f262014-10-12 12:35:20 -0700681
682 Fib& fib = forwarder.getFib();
Junxiao Shia6de4292016-07-12 02:08:10 +0000683 fib.insert("/A").first->addNextHop(*face2, 0);
Junxiao Shia110f262014-10-12 12:35:20 -0700684
Junxiao Shi455581d2014-11-17 18:38:40 -0700685 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700686 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
687 interest->setNonce(82101183);
688 interest->setInterestLifetime(time::milliseconds(50));
689 face1->receiveInterest(*interest);
690
Junxiao Shi455581d2014-11-17 18:38:40 -0700691 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
692 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
693 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700694
Junxiao Shicde37ad2015-12-24 01:02:05 -0700695 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700696
697 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
698 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
699 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
700 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
701 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700702}
703
Junxiao Shid41d6072016-06-19 23:35:27 +0000704BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700705{
706 Forwarder forwarder;
707 shared_ptr<Face> face1 = make_shared<DummyFace>();
708 forwarder.addFace(face1);
709
710 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
711 interest->setNonce(61883075);
712 interest->setInterestLifetime(time::seconds(2));
713
714 DeadNonceList& dnl = forwarder.getDeadNonceList();
715 dnl.add(interest->getName(), interest->getNonce());
716 Pit& pit = forwarder.getPit();
717 BOOST_REQUIRE_EQUAL(pit.size(), 0);
718
719 forwarder.startProcessInterest(*face1, *interest);
720 this->advanceClocks(time::milliseconds(100), time::seconds(20));
721 BOOST_CHECK_EQUAL(pit.size(), 0);
722}
723
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700724BOOST_AUTO_TEST_CASE(LinkDelegation)
725{
726 Forwarder forwarder;
727 shared_ptr<Face> face1 = make_shared<DummyFace>();
728 shared_ptr<Face> face2 = make_shared<DummyFace>();
729 forwarder.addFace(face1);
730 forwarder.addFace(face2);
731
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700732 Fib& fib = forwarder.getFib();
733 Pit& pit = forwarder.getPit();
734 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
735
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700736 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
737
738 // consumer region
739 nrt.clear();
740 nrt.insert("/arizona/cs/avenir");
Junxiao Shia6de4292016-07-12 02:08:10 +0000741 fib.insert("/").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700742
743 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
744 interest1->setLink(link->wireEncode());
745 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
746 pit1->insertOrUpdateInRecord(face1, *interest1);
747
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000748 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700749 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
750
Junxiao Shia6de4292016-07-12 02:08:10 +0000751 fib.insert("/").first->removeNextHop(*face2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700752
753 // first default-free router, both delegations are available
754 nrt.clear();
755 nrt.insert("/arizona/cs/hobo");
Junxiao Shia6de4292016-07-12 02:08:10 +0000756 fib.insert("/telia").first->addNextHop(*face2, 10);
757 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700758
759 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
760 interest2->setLink(link->wireEncode());
761 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
762 pit2->insertOrUpdateInRecord(face1, *interest2);
763
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000764 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit2).getPrefix(), "/telia");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700765 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
766 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
767
Junxiao Shia6de4292016-07-12 02:08:10 +0000768 fib.erase("/telia");
769 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700770
771 // first default-free router, only second delegation is available
772 nrt.clear();
773 nrt.insert("/arizona/cs/hobo");
Junxiao Shia6de4292016-07-12 02:08:10 +0000774 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700775
776 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
777 interest3->setLink(link->wireEncode());
778 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
779 pit3->insertOrUpdateInRecord(face1, *interest3);
780
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000781 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit3).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700782 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
783 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
784
Junxiao Shia6de4292016-07-12 02:08:10 +0000785 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700786
787 // default-free router, chosen SelectedDelegation
788 nrt.clear();
789 nrt.insert("/ucsd/caida/click");
Junxiao Shia6de4292016-07-12 02:08:10 +0000790 fib.insert("/telia").first->addNextHop(*face2, 10);
791 fib.insert("/ucla").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700792
793 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
794 interest4->setLink(link->wireEncode());
795 interest4->setSelectedDelegation("/ucla/cs");
796 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
797 pit4->insertOrUpdateInRecord(face1, *interest4);
798
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000799 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit4).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700800 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
801 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
802
Junxiao Shia6de4292016-07-12 02:08:10 +0000803 fib.erase("/telia");
804 fib.erase("/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700805
806 // producer region
807 nrt.clear();
808 nrt.insert("/ucla/cs/spurs");
Junxiao Shia6de4292016-07-12 02:08:10 +0000809 fib.insert("/").first->addNextHop(*face2, 10);
810 fib.insert("/ucla").first->addNextHop(*face2, 10);
811 fib.insert("/net/ndnsim").first->addNextHop(*face2, 10);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700812
813 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
814 interest5->setLink(link->wireEncode());
815 interest5->setSelectedDelegation("/ucla/cs");
816 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
817 pit5->insertOrUpdateInRecord(face1, *interest5);
818
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000819 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/net/ndnsim");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700820 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
821 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
822
Junxiao Shia6de4292016-07-12 02:08:10 +0000823 fib.insert("/").first->removeNextHop(*face2);
824 fib.erase("/ucla");
825 fib.erase("/ndnsim");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700826}
827
828
829class MalformedPacketFixture : public UnitTestTimeFixture
830{
831protected:
832 MalformedPacketFixture()
833 : face1(make_shared<DummyFace>())
834 , face2(make_shared<DummyFace>())
835 {
836 forwarder.addFace(face1);
837 forwarder.addFace(face2);
838 }
839
840 void
841 processInterest(shared_ptr<Interest> badInterest)
842 {
843 forwarder.startProcessInterest(*face1, *badInterest);
844 this->continueProcessPacket();
845 }
846
847 // processData
848
849 // processNack
850
851private:
852 void
853 continueProcessPacket()
854 {
855 this->advanceClocks(time::milliseconds(10), time::seconds(6));
856 }
857
858protected:
859 Forwarder forwarder;
860 shared_ptr<DummyFace> face1; // face of incoming bad packet
861 shared_ptr<DummyFace> face2; // another face for setting up states
862};
863
864BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
865
866BOOST_AUTO_TEST_CASE(BadLink)
867{
868 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
869 Block wire = goodInterest->wireEncode();
870 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
871 wire.encode();
872
873 auto badInterest = make_shared<Interest>();
874 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
875 BOOST_REQUIRE(badInterest->hasLink());
876 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
877
878 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
879}
880
881BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
882
883BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700884BOOST_AUTO_TEST_SUITE_END()
885
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700886} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700887} // namespace nfd